You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by ev...@apache.org on 2013/12/12 19:30:31 UTC
git commit: Properly set the request method in HTTPS connections
Updated Branches:
refs/heads/master 828d8790c -> cec0981bb
Properly set the request method in HTTPS connections
Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/cec0981b
Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/cec0981b
Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/cec0981b
Branch: refs/heads/master
Commit: cec0981bb925d6ccaf048727ae064a3827b3d1c3
Parents: 828d879
Author: Ignasi Barrera <na...@apache.org>
Authored: Thu Dec 12 16:25:16 2013 +0100
Committer: Everett Toews <ev...@rackspace.com>
Committed: Thu Dec 12 12:30:06 2013 -0600
----------------------------------------------------------------------
.../JavaUrlHttpCommandExecutorService.java | 65 ++++++++++++++++----
1 file changed, 52 insertions(+), 13 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jclouds/blob/cec0981b/core/src/main/java/org/jclouds/http/internal/JavaUrlHttpCommandExecutorService.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/jclouds/http/internal/JavaUrlHttpCommandExecutorService.java b/core/src/main/java/org/jclouds/http/internal/JavaUrlHttpCommandExecutorService.java
index 9a8cb90..3e2b5db 100644
--- a/core/src/main/java/org/jclouds/http/internal/JavaUrlHttpCommandExecutorService.java
+++ b/core/src/main/java/org/jclouds/http/internal/JavaUrlHttpCommandExecutorService.java
@@ -78,7 +78,6 @@ public class JavaUrlHttpCommandExecutorService extends BaseHttpCommandExecutorSe
private final Supplier<SSLContext> untrustedSSLContextProvider;
private final Function<URI, Proxy> proxyForURI;
private final HostnameVerifier verifier;
- private final Field methodField;
@Inject(optional = true)
Supplier<SSLContext> sslContextSupplier;
@@ -95,8 +94,6 @@ public class JavaUrlHttpCommandExecutorService extends BaseHttpCommandExecutorSe
this.untrustedSSLContextProvider = checkNotNull(untrustedSSLContextProvider, "untrustedSSLContextProvider");
this.verifier = checkNotNull(verifier, "verifier");
this.proxyForURI = checkNotNull(proxyForURI, "proxyForURI");
- this.methodField = HttpURLConnection.class.getDeclaredField("method");
- this.methodField.setAccessible(true);
}
@Override
@@ -174,16 +171,8 @@ public class JavaUrlHttpCommandExecutorService extends BaseHttpCommandExecutorSe
// ex. Caused by: java.io.IOException: HTTPS hostname wrong: should be
// <adriancole.s3int0.s3-external-3.amazonaws.com>
connection.setInstanceFollowRedirects(false);
- try {
- connection.setRequestMethod(request.getMethod());
- } catch (ProtocolException e) {
- try {
- methodField.set(connection, request.getMethod());
- } catch (IllegalAccessException e1) {
- logger.error(e, "could not set request method: ", request.getMethod());
- propagate(e1);
- }
- }
+
+ setRequestMethodBypassingJREMethodLimitation(connection, request.getMethod());
for (Map.Entry<String, String> entry : request.getHeaders().entries()) {
connection.setRequestProperty(entry.getKey(), entry.getValue());
@@ -227,6 +216,56 @@ public class JavaUrlHttpCommandExecutorService extends BaseHttpCommandExecutorSe
return connection;
}
+ /**
+ * Workaround for a bug in <code>HttpURLConnection.setRequestMethod(String)</code>
+ * The implementation of Sun Microsystems is throwing a <code>ProtocolException</code>
+ * when the method is other than the HTTP/1.1 default methods. So
+ * to use PATCH and others, we must apply this workaround.
+ *
+ * See issue http://java.net/jira/browse/JERSEY-639
+ */
+ private void setRequestMethodBypassingJREMethodLimitation(final HttpURLConnection httpURLConnection, final String method) {
+ try {
+ httpURLConnection.setRequestMethod(method);
+ // If the JRE does not support the given method, set it using reflection
+ } catch (final ProtocolException pe) {
+ Class<?> connectionClass = httpURLConnection.getClass();
+ Field delegateField = null;
+ try {
+ // SSL connections may have the HttpURLConnection wrapped inside
+ delegateField = connectionClass.getDeclaredField("delegate");
+ delegateField.setAccessible(true);
+ HttpURLConnection delegateConnection = (HttpURLConnection) delegateField.get(httpURLConnection);
+ setRequestMethodBypassingJREMethodLimitation(delegateConnection, method);
+ } catch (NoSuchFieldException e) {
+ // Ignore for now, keep going
+ } catch (IllegalArgumentException e) {
+ logger.error(e, "could not set request method: ", method);
+ propagate(e);
+ } catch (IllegalAccessException e) {
+ logger.error(e, "could not set request method: ", method);
+ propagate(e);
+ }
+ try {
+ Field methodField = null;
+ while (connectionClass != null) {
+ try {
+ methodField = connectionClass.getDeclaredField("method");
+ } catch (NoSuchFieldException e) {
+ connectionClass = connectionClass.getSuperclass();
+ continue;
+ }
+ methodField.setAccessible(true);
+ methodField.set(httpURLConnection, method);
+ break;
+ }
+ } catch (final Exception e) {
+ logger.error(e, "could not set request method: ", method);
+ propagate(e);
+ }
+ }
+ }
+
protected void writeNothing(HttpURLConnection connection) {
if (!HttpRequest.NON_PAYLOAD_METHODS.contains(connection.getRequestMethod())) {
connection.setRequestProperty(CONTENT_LENGTH, "0");