Merge pull request #1279 from jclouds/get-becomes-post

worked around issue where GET can become POST
This commit is contained in:
Adrian Cole 2013-01-31 18:10:37 -08:00
commit 95add25125
1 changed files with 25 additions and 22 deletions

View File

@ -63,6 +63,7 @@ import com.google.common.base.Function;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableMultimap.Builder; import com.google.common.collect.ImmutableMultimap.Builder;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.CountingOutputStream; import com.google.common.io.CountingOutputStream;
import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.inject.Inject; import com.google.inject.Inject;
@ -85,7 +86,6 @@ public class JavaUrlHttpCommandExecutorService extends BaseHttpCommandExecutorSe
@Inject(optional = true) @Inject(optional = true)
Supplier<SSLContext> sslContextSupplier; Supplier<SSLContext> sslContextSupplier;
@Inject @Inject
public JavaUrlHttpCommandExecutorService(HttpUtils utils, ContentMetadataCodec contentMetadataCodec, public JavaUrlHttpCommandExecutorService(HttpUtils utils, ContentMetadataCodec contentMetadataCodec,
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ListeningExecutorService ioExecutor, @Named(Constants.PROPERTY_IO_WORKER_THREADS) ListeningExecutorService ioExecutor,
@ -100,7 +100,7 @@ public class JavaUrlHttpCommandExecutorService extends BaseHttpCommandExecutorSe
this.verifier = checkNotNull(verifier, "verifier"); this.verifier = checkNotNull(verifier, "verifier");
this.proxyForURI = checkNotNull(proxyForURI, "proxyForURI"); this.proxyForURI = checkNotNull(proxyForURI, "proxyForURI");
this.methodField = HttpURLConnection.class.getDeclaredField("method"); this.methodField = HttpURLConnection.class.getDeclaredField("method");
methodField.setAccessible(true); this.methodField.setAccessible(true);
} }
@Override @Override
@ -173,7 +173,6 @@ public class JavaUrlHttpCommandExecutorService extends BaseHttpCommandExecutorSe
} }
connection.setConnectTimeout(utils.getConnectionTimeout()); connection.setConnectTimeout(utils.getConnectionTimeout());
connection.setReadTimeout(utils.getSocketOpenTimeout()); connection.setReadTimeout(utils.getSocketOpenTimeout());
connection.setDoOutput(true);
connection.setAllowUserInteraction(false); connection.setAllowUserInteraction(false);
// do not follow redirects since https redirects don't work properly // do not follow redirects since https redirects don't work properly
// ex. Caused by: java.io.IOException: HTTPS hostname wrong: should be // ex. Caused by: java.io.IOException: HTTPS hostname wrong: should be
@ -184,7 +183,7 @@ public class JavaUrlHttpCommandExecutorService extends BaseHttpCommandExecutorSe
} catch (ProtocolException e) { } catch (ProtocolException e) {
try { try {
methodField.set(connection, request.getMethod()); methodField.set(connection, request.getMethod());
} catch (Exception e1) { } catch (IllegalAccessException e1) {
logger.error(e, "could not set request method: ", request.getMethod()); logger.error(e, "could not set request method: ", request.getMethod());
propagate(e1); propagate(e1);
} }
@ -202,40 +201,45 @@ public class JavaUrlHttpCommandExecutorService extends BaseHttpCommandExecutorSe
if (connection.getRequestProperty(USER_AGENT) == null) { if (connection.getRequestProperty(USER_AGENT) == null) {
connection.setRequestProperty(USER_AGENT, DEFAULT_USER_AGENT); connection.setRequestProperty(USER_AGENT, DEFAULT_USER_AGENT);
} }
Payload payload = request.getPayload();
if (request.getPayload() != null) { if (payload != null) {
MutableContentMetadata md = request.getPayload().getContentMetadata(); MutableContentMetadata md = payload.getContentMetadata();
for (Map.Entry<String,String> entry : contentMetadataCodec.toHeaders(md).entries()) { for (Map.Entry<String,String> entry : contentMetadataCodec.toHeaders(md).entries()) {
connection.setRequestProperty(entry.getKey(), entry.getValue()); connection.setRequestProperty(entry.getKey(), entry.getValue());
} }
if (chunked) { if (chunked) {
connection.setChunkedStreamingMode(8196); connection.setChunkedStreamingMode(8196);
} else { } else {
Long length = checkNotNull(md.getContentLength(), "payload.getContentLength"); long length = checkNotNull(md.getContentLength(), "payload.getContentLength");
connection.setRequestProperty(CONTENT_LENGTH, length.toString());
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6755625 // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6755625
checkArgument(length < Integer.MAX_VALUE, checkArgument(length < Integer.MAX_VALUE,
"JDK 1.6 does not support >2GB chunks. Use chunked encoding, if possible."); "JDK 1.6 does not support >2GB chunks. Use chunked encoding, if possible.");
connection.setFixedLengthStreamingMode(length.intValue()); connection.setRequestProperty(CONTENT_LENGTH, length + "");
if (length.intValue() > 0) { if (length > 0) {
connection.setRequestProperty("Expect", "100-continue"); writePayloadToConnection(payload, connection);
} }
} }
CountingOutputStream out = new CountingOutputStream(connection.getOutputStream());
try {
request.getPayload().writeTo(out);
} catch (IOException e) {
throw new RuntimeException(String.format("error after writing %d/%s bytes to %s", out.getCount(), md
.getContentLength(), request.getRequestLine()), e);
}
} else { } else {
connection.setRequestProperty(CONTENT_LENGTH, "0"); connection.setRequestProperty(CONTENT_LENGTH, "0");
// for some reason POST/PUT undoes the content length header above. // for some reason POST/PUT undoes the content length header above.
if (connection.getRequestMethod().equals("POST") || connection.getRequestMethod().equals("PUT")) if (ImmutableSet.of("POST", "PUT").contains(connection.getRequestMethod()))
connection.setFixedLengthStreamingMode(0); connection.setFixedLengthStreamingMode(0);
} }
return connection; return connection;
}
void writePayloadToConnection(Payload payload, HttpURLConnection connection) throws IOException {
Long length = payload.getContentMetadata().getContentLength();
connection.setFixedLengthStreamingMode(length.intValue());
connection.setDoOutput(true);
connection.setRequestProperty("Expect", "100-continue");
CountingOutputStream out = new CountingOutputStream(connection.getOutputStream());
try {
payload.writeTo(out);
} catch (IOException e) {
logger.error(e, "error after writing %d/%s bytes to %s", out.getCount(), length, connection.getURL());
throw e;
}
} }
@Override @Override
@ -243,5 +247,4 @@ public class JavaUrlHttpCommandExecutorService extends BaseHttpCommandExecutorSe
if (connection != null) if (connection != null)
connection.disconnect(); connection.disconnect();
} }
} }