HttpUrlConnector extension (#4613)
* Created HttpUrlConnector extension for Http100Continue
Signed-off-by: Maxim Nesen <maxim.nesen@oracle.com>
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/internal/ConnectorExtension.java b/core-client/src/main/java/org/glassfish/jersey/client/internal/ConnectorExtension.java
new file mode 100644
index 0000000..022cbc6
--- /dev/null
+++ b/core-client/src/main/java/org/glassfish/jersey/client/internal/ConnectorExtension.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.client.internal;
+
+import org.glassfish.jersey.client.ClientRequest;
+
+/**
+ * Connector extension interface to extend existing connector's functionality.
+ *
+ * @param <T> type of connection to be extended/processed
+ * @param <E> type of exception which can be thrown while processing/handling exeption
+ *
+ * @since 2.33
+ */
+interface ConnectorExtension<T, E extends Exception> {
+
+ /**
+ * Main function which allows extension of connector's functionality
+ *
+ * @param request request instance to work with (shall contain all required settings/params to be used in extension)
+ * @param extensionParam connector's instance which is being extended
+ */
+ void invoke(ClientRequest request, T extensionParam);
+
+ /**
+ * After connection is done some additional work may be done
+ *
+ * @param extensionParam connector's instance which is being extended
+ */
+ void postConnectionProcessing(T extensionParam);
+
+ /**
+ * Exception handling method
+ *
+ * @param request request instance to work with (shall contain all required settings/params to be used in extension)
+ * @param ex exception instance which comes from connector
+ * @param extensionParam connector's instance which is being extended
+ * @return true if exception was handled by this method, false otherwise
+ * @throws E can thor exception if required by handling
+ */
+ boolean handleException(ClientRequest request, T extensionParam, E ex) throws E;
+
+}
\ No newline at end of file
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlConnector.java b/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlConnector.java
index 0f0614c..777ed40 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlConnector.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlConnector.java
@@ -102,6 +102,9 @@
private final boolean isRestrictedHeaderPropertySet;
private final LazyValue<SSLSocketFactory> sslSocketFactory;
+ private final ConnectorExtension<HttpURLConnection, IOException> connectorExtension
+ = new HttpUrlExpect100ContinueConnectorExtension();
+
/**
* Create new {@code HttpUrlConnector} instance.
*
@@ -352,7 +355,7 @@
}
}
- processExpect100Continue(request, uc, length, entityProcessing);
+ processExtentions(request, uc);
request.setStreamProvider(contentLength -> {
setOutboundHeaders(request.getStringHeaders(), uc);
@@ -364,11 +367,7 @@
setOutboundHeaders(request.getStringHeaders(), uc);
}
} catch (IOException ioe) {
- if (uc.getResponseCode() == -1) {
- throw ioe;
- } else {
- storedException = ioe;
- }
+ storedException = handleException(request, ioe, uc);
}
final int code = uc.getResponseCode();
@@ -530,24 +529,19 @@
}
}
- private static void processExpect100Continue(ClientRequest request, HttpURLConnection uc,
- long length, RequestEntityProcessing entityProcessing) {
- final Boolean expectContinueActivated = request.resolveProperty(
- ClientProperties.EXPECT_100_CONTINUE, Boolean.class);
- final Long expectContinueSizeThreshold = request.resolveProperty(
- ClientProperties.EXPECT_100_CONTINUE_THRESHOLD_SIZE,
- ClientProperties.DEFAULT_EXPECT_100_CONTINUE_THRESHOLD_SIZE);
+ private void processExtentions(ClientRequest request, HttpURLConnection uc) {
+ connectorExtension.invoke(request, uc);
+ }
- final boolean allowStreaming = length > expectContinueSizeThreshold
- || entityProcessing == RequestEntityProcessing.CHUNKED;
-
- if (!Boolean.TRUE.equals(expectContinueActivated)
- || !("POST".equals(uc.getRequestMethod()) || "PUT".equals(uc.getRequestMethod()))
- || !allowStreaming
- ) {
- return;
+ private IOException handleException(ClientRequest request, IOException ex, HttpURLConnection uc) throws IOException {
+ if (connectorExtension.handleException(request, uc, ex)) {
+ return null;
}
- uc.setRequestProperty("Expect", "100-Continue");
+ if (uc.getResponseCode() == -1) {
+ throw ex;
+ } else {
+ return ex;
+ }
}
@Override
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlExpect100ContinueConnectorExtension.java b/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlExpect100ContinueConnectorExtension.java
new file mode 100644
index 0000000..2e727eb
--- /dev/null
+++ b/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlExpect100ContinueConnectorExtension.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.client.internal;
+
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.client.ClientRequest;
+import org.glassfish.jersey.client.RequestEntityProcessing;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.ProtocolException;
+
+class HttpUrlExpect100ContinueConnectorExtension
+ implements ConnectorExtension<HttpURLConnection, IOException> {
+
+ private static final String EXCEPTION_MESSAGE = "Server rejected operation";
+
+ @Override
+ public void invoke(ClientRequest request, HttpURLConnection uc) {
+
+ final long length = request.getLengthLong();
+ final RequestEntityProcessing entityProcessing = request.resolveProperty(
+ ClientProperties.REQUEST_ENTITY_PROCESSING, RequestEntityProcessing.class);
+
+ final Boolean expectContinueActivated = request.resolveProperty(
+ ClientProperties.EXPECT_100_CONTINUE, Boolean.class);
+ final Long expectContinueSizeThreshold = request.resolveProperty(
+ ClientProperties.EXPECT_100_CONTINUE_THRESHOLD_SIZE,
+ ClientProperties.DEFAULT_EXPECT_100_CONTINUE_THRESHOLD_SIZE);
+
+ final boolean allowStreaming = length > expectContinueSizeThreshold
+ || entityProcessing == RequestEntityProcessing.CHUNKED;
+
+ if (!Boolean.TRUE.equals(expectContinueActivated)
+ || !("POST".equals(uc.getRequestMethod()) || "PUT".equals(uc.getRequestMethod()))
+ || !allowStreaming
+ ) {
+ return;
+ }
+ uc.setRequestProperty("Expect", "100-Continue");
+ }
+
+ @Override
+ public void postConnectionProcessing(HttpURLConnection extensionParam) {
+ //nothing here, we do not process post connection extension
+ }
+
+ @Override
+ public boolean handleException(ClientRequest request, HttpURLConnection extensionParam, IOException ex) {
+
+ final Boolean expectContinueActivated = request.resolveProperty(
+ ClientProperties.EXPECT_100_CONTINUE, Boolean.FALSE);
+
+ return expectContinueActivated
+ && (ex instanceof ProtocolException && ex.getMessage().equals(EXCEPTION_MESSAGE));
+ }
+
+}
\ No newline at end of file