Merge pull request #1383 from jclouds/remove-expect-100

remove default add of Expect 100 Continue header
This commit is contained in:
Adrian Cole 2013-03-03 22:13:24 -08:00
commit 1ab2bea92a
32 changed files with 186 additions and 118 deletions

View File

@ -18,6 +18,8 @@
*/ */
package org.jclouds.atmos; package org.jclouds.atmos;
import static com.google.common.net.HttpHeaders.EXPECT;
import java.net.URI; import java.net.URI;
import javax.inject.Named; import javax.inject.Named;
@ -56,6 +58,7 @@ import org.jclouds.blobstore.BlobStoreFallbacks.ThrowKeyNotFoundOn404;
import org.jclouds.http.options.GetOptions; import org.jclouds.http.options.GetOptions;
import org.jclouds.rest.annotations.BinderParam; import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.Fallback; import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.Headers;
import org.jclouds.rest.annotations.ParamParser; import org.jclouds.rest.annotations.ParamParser;
import org.jclouds.rest.annotations.QueryParams; import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.RequestFilters;
@ -119,6 +122,7 @@ public interface AtmosAsyncClient {
@Named("CreateObject") @Named("CreateObject")
@POST @POST
@Path("/{parent}/{name}") @Path("/{parent}/{name}")
@Headers(keys = EXPECT, values = "100-continue")
@Consumes(MediaType.WILDCARD) @Consumes(MediaType.WILDCARD)
ListenableFuture<URI> createFile( ListenableFuture<URI> createFile(
@PathParam("parent") String parent, @PathParam("parent") String parent,
@ -131,6 +135,7 @@ public interface AtmosAsyncClient {
@Named("UpdateObject") @Named("UpdateObject")
@PUT @PUT
@Path("/{parent}/{name}") @Path("/{parent}/{name}")
@Headers(keys = EXPECT, values = "100-continue")
@Fallback(ThrowKeyNotFoundOn404.class) @Fallback(ThrowKeyNotFoundOn404.class)
@Consumes(MediaType.WILDCARD) @Consumes(MediaType.WILDCARD)
ListenableFuture<Void> updateFile( ListenableFuture<Void> updateFile(

View File

@ -167,7 +167,7 @@ public class AtmosAsyncClientTest extends BaseAsyncClientTest<AtmosAsyncClient>
.apply(BindBlobToMultipartFormTest.TEST_BLOB))); .apply(BindBlobToMultipartFormTest.TEST_BLOB)));
assertRequestLineEquals(request, "POST https://accesspoint.atmosonline.com/rest/namespace/dir/hello HTTP/1.1"); assertRequestLineEquals(request, "POST https://accesspoint.atmosonline.com/rest/namespace/dir/hello HTTP/1.1");
assertNonPayloadHeadersEqual(request, HttpHeaders.ACCEPT + ": */*\n"); assertNonPayloadHeadersEqual(request, HttpHeaders.ACCEPT + ": */*\nExpect: 100-continue\n");
assertPayloadEquals(request, "hello", "text/plain", false); assertPayloadEquals(request, "hello", "text/plain", false);
assertResponseParserClassEquals(method, request, ParseURIFromListOrLocationHeaderIf20x.class); assertResponseParserClassEquals(method, request, ParseURIFromListOrLocationHeaderIf20x.class);
@ -185,7 +185,7 @@ public class AtmosAsyncClientTest extends BaseAsyncClientTest<AtmosAsyncClient>
assertRequestLineEquals(request, "POST https://accesspoint.atmosonline.com/rest/namespace/dir/hello HTTP/1.1"); assertRequestLineEquals(request, "POST https://accesspoint.atmosonline.com/rest/namespace/dir/hello HTTP/1.1");
assertNonPayloadHeadersEqual(request, HttpHeaders.ACCEPT assertNonPayloadHeadersEqual(request, HttpHeaders.ACCEPT
+ ": */*\nx-emc-groupacl: other=READ\nx-emc-useracl: root=FULL_CONTROL\n"); + ": */*\nExpect: 100-continue\nx-emc-groupacl: other=READ\nx-emc-useracl: root=FULL_CONTROL\n");
assertPayloadEquals(request, "hello", "text/plain", false); assertPayloadEquals(request, "hello", "text/plain", false);
assertResponseParserClassEquals(method, request, ParseURIFromListOrLocationHeaderIf20x.class); assertResponseParserClassEquals(method, request, ParseURIFromListOrLocationHeaderIf20x.class);
@ -202,7 +202,7 @@ public class AtmosAsyncClientTest extends BaseAsyncClientTest<AtmosAsyncClient>
.apply(BindBlobToMultipartFormTest.TEST_BLOB))); .apply(BindBlobToMultipartFormTest.TEST_BLOB)));
assertRequestLineEquals(request, "PUT https://accesspoint.atmosonline.com/rest/namespace/dir/hello HTTP/1.1"); assertRequestLineEquals(request, "PUT https://accesspoint.atmosonline.com/rest/namespace/dir/hello HTTP/1.1");
assertNonPayloadHeadersEqual(request, HttpHeaders.ACCEPT + ": */*\n"); assertNonPayloadHeadersEqual(request, HttpHeaders.ACCEPT + ": */*\nExpect: 100-continue\n");
assertPayloadEquals(request, "hello", "text/plain", false); assertPayloadEquals(request, "hello", "text/plain", false);
assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class); assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
@ -220,7 +220,7 @@ public class AtmosAsyncClientTest extends BaseAsyncClientTest<AtmosAsyncClient>
assertRequestLineEquals(request, "PUT https://accesspoint.atmosonline.com/rest/namespace/dir/hello HTTP/1.1"); assertRequestLineEquals(request, "PUT https://accesspoint.atmosonline.com/rest/namespace/dir/hello HTTP/1.1");
assertNonPayloadHeadersEqual(request, HttpHeaders.ACCEPT assertNonPayloadHeadersEqual(request, HttpHeaders.ACCEPT
+ ": */*\nx-emc-groupacl: other=READ\nx-emc-useracl: root=FULL_CONTROL\n"); + ": */*\nExpect: 100-continue\nx-emc-groupacl: other=READ\nx-emc-useracl: root=FULL_CONTROL\n");
assertPayloadEquals(request, "hello", "text/plain", false); assertPayloadEquals(request, "hello", "text/plain", false);
assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class); assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);

View File

@ -101,7 +101,7 @@ public class AtmosBlobRequestSignerTest extends BaseAsyncClientTest<AtmosAsyncCl
"POST https://accesspoint.atmosonline.com/rest/namespace/container/name HTTP/1.1"); "POST https://accesspoint.atmosonline.com/rest/namespace/container/name HTTP/1.1");
assertNonPayloadHeadersEqual( assertNonPayloadHeadersEqual(
request, request,
"Accept: */*\nDate: Thu, 05 Jun 2008 16:38:19 GMT\nx-emc-signature: 7Cbdnu+YA5rG9J/C9RlHk07mU7w=\nx-emc-uid: identity\n"); "Accept: */*\nDate: Thu, 05 Jun 2008 16:38:19 GMT\nExpect: 100-continue\nx-emc-signature: 7Cbdnu+YA5rG9J/C9RlHk07mU7w=\nx-emc-uid: identity\n");
assertContentHeadersEqual(request, "text/plain", null, null, null, (long) 2l, new byte[] { 0, 2, 4, 8 }, new Date(1000)); assertContentHeadersEqual(request, "text/plain", null, null, null, (long) 2l, new byte[] { 0, 2, 4, 8 }, new Date(1000));

View File

@ -80,12 +80,14 @@ public class CloudFilesBlobSignerExpectTest extends BaseBlobSignerExpectTest {
protected HttpRequest putBlob() { protected HttpRequest putBlob() {
return HttpRequest.builder().method("PUT") return HttpRequest.builder().method("PUT")
.endpoint("https://storage101.lon3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953/container/name") .endpoint("https://storage101.lon3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953/container/name")
.addHeader("Expect", "100-continue")
.addHeader("X-Auth-Token", authToken).build(); .addHeader("X-Auth-Token", authToken).build();
} }
@Override @Override
protected HttpRequest putBlobWithTime() { protected HttpRequest putBlobWithTime() {
return HttpRequest.builder().method("PUT") return HttpRequest.builder().method("PUT")
.addHeader("Expect", "100-continue")
.endpoint("https://storage101.lon3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953/container/name?temp_url_sig=f83fa711f353f6f0bab3a66c56e35a972b9b3922&temp_url_expires=123456792").build(); .endpoint("https://storage101.lon3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953/container/name?temp_url_sig=f83fa711f353f6f0bab3a66c56e35a972b9b3922&temp_url_expires=123456792").build();
} }

View File

@ -18,6 +18,7 @@
*/ */
package org.jclouds.s3; package org.jclouds.s3;
import static com.google.common.net.HttpHeaders.EXPECT;
import static org.jclouds.blobstore.attr.BlobScopes.CONTAINER; import static org.jclouds.blobstore.attr.BlobScopes.CONTAINER;
import java.util.Set; import java.util.Set;
@ -168,6 +169,7 @@ public interface S3AsyncClient {
@Named("PutObject") @Named("PutObject")
@PUT @PUT
@Path("/{key}") @Path("/{key}")
@Headers(keys = EXPECT, values = "100-continue")
@ResponseParser(ParseETagHeader.class) @ResponseParser(ParseETagHeader.class)
ListenableFuture<String> putObject( ListenableFuture<String> putObject(
@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName, @Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName,

View File

@ -82,6 +82,7 @@ public class PathBasedS3ClientExpectTest extends BaseS3ClientExpectTest {
HttpRequest bucketFooExists = HttpRequest.builder().method("PUT") HttpRequest bucketFooExists = HttpRequest.builder().method("PUT")
.endpoint("https://s3.amazonaws.com/bucket/object") .endpoint("https://s3.amazonaws.com/bucket/object")
.addHeader("Expect", "100-continue")
.addHeader("Date", CONSTANT_DATE) .addHeader("Date", CONSTANT_DATE)
.addHeader("Authorization", "AWS identity:6gC0m7SYFDPwkUqY5EHV/6i9DfM=") .addHeader("Authorization", "AWS identity:6gC0m7SYFDPwkUqY5EHV/6i9DfM=")
.payload("hello world") .payload("hello world")

View File

@ -20,7 +20,10 @@ package org.jclouds.s3;
import static com.google.common.net.HttpHeaders.CONTENT_LENGTH; import static com.google.common.net.HttpHeaders.CONTENT_LENGTH;
import static com.google.common.net.HttpHeaders.ETAG; import static com.google.common.net.HttpHeaders.ETAG;
import static com.google.common.net.HttpHeaders.EXPECT;
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor; import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
import static org.jclouds.Constants.PROPERTY_MAX_RETRIES;
import static org.jclouds.Constants.PROPERTY_SO_TIMEOUT;
import static org.jclouds.s3.reference.S3Constants.PROPERTY_S3_VIRTUAL_HOST_BUCKETS; import static org.jclouds.s3.reference.S3Constants.PROPERTY_S3_VIRTUAL_HOST_BUCKETS;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
@ -46,7 +49,7 @@ import com.google.mockwebserver.RecordedRequest;
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test @Test(singleThreaded = true)
public class S3ClientMockTest { public class S3ClientMockTest {
private static final Set<Module> modules = ImmutableSet.<Module> of( private static final Set<Module> modules = ImmutableSet.<Module> of(
@ -55,7 +58,9 @@ public class S3ClientMockTest {
static RestContext<? extends S3Client,? extends S3AsyncClient> getContext(URL server) { static RestContext<? extends S3Client,? extends S3AsyncClient> getContext(URL server) {
Properties overrides = new Properties(); Properties overrides = new Properties();
overrides.setProperty(PROPERTY_S3_VIRTUAL_HOST_BUCKETS, "false"); overrides.setProperty(PROPERTY_S3_VIRTUAL_HOST_BUCKETS, "false");
// prevent expect-100 bug http://code.google.com/p/mockwebserver/issues/detail?id=6
overrides.setProperty(PROPERTY_SO_TIMEOUT, "0");
overrides.setProperty(PROPERTY_MAX_RETRIES, "1");
return ContextBuilder.newBuilder("s3") return ContextBuilder.newBuilder("s3")
.credentials("accessKey", "secretKey") .credentials("accessKey", "secretKey")
.endpoint(server.toString()) .endpoint(server.toString())
@ -79,24 +84,28 @@ public class S3ClientMockTest {
RecordedRequest request = server.takeRequest(); RecordedRequest request = server.takeRequest();
assertEquals(request.getRequestLine(), "PUT /bucket/object HTTP/1.1"); assertEquals(request.getRequestLine(), "PUT /bucket/object HTTP/1.1");
assertEquals(request.getHeaders(CONTENT_LENGTH), ImmutableList.of("0")); assertEquals(request.getHeaders(CONTENT_LENGTH), ImmutableList.of("0"));
// will fail unless -Dsun.net.http.allowRestrictedHeaders=true is set
assertEquals(request.getHeaders(EXPECT), ImmutableList.of("100-continue"));
server.shutdown(); server.shutdown();
} }
public void testDirectorySeparator() throws IOException, InterruptedException { public void testDirectorySeparator() throws IOException, InterruptedException {
MockWebServer server = new MockWebServer(); MockWebServer server = new MockWebServer();
server.enqueue(new MockResponse().setBody("").addHeader(ETAG, "ABCDEF")); server.enqueue(new MockResponse().setBody("").addHeader(ETAG, "ABCDEF"));
server.play(); server.play();
S3Client client = getContext(server.getUrl("/")).getApi(); S3Client client = getContext(server.getUrl("/")).getApi();
S3Object fileInDir = client.newS3Object(); S3Object fileInDir = client.newS3Object();
fileInDir.getMetadata().setKey("someDir/fileName"); fileInDir.getMetadata().setKey("someDir/fileName");
fileInDir.setPayload(new byte[] {}); fileInDir.setPayload(new byte[] { 1, 2, 3, 4 });
assertEquals(client.putObject("bucket", fileInDir), "ABCDEF"); assertEquals(client.putObject("bucket", fileInDir), "ABCDEF");
RecordedRequest request = server.takeRequest(); RecordedRequest request = server.takeRequest();
assertEquals(request.getRequestLine(), "PUT /bucket/someDir/fileName HTTP/1.1"); assertEquals(request.getRequestLine(), "PUT /bucket/someDir/fileName HTTP/1.1");
// will fail unless -Dsun.net.http.allowRestrictedHeaders=true is set
assertEquals(request.getHeaders(EXPECT), ImmutableList.of("100-continue"));
server.shutdown(); server.shutdown();
} }
} }

View File

@ -82,6 +82,7 @@ public class S3BlobSignerExpectTest extends BaseBlobSignerExpectTest {
protected HttpRequest putBlob() { protected HttpRequest putBlob() {
return HttpRequest.builder().method("PUT") return HttpRequest.builder().method("PUT")
.endpoint("https://container.s3.amazonaws.com/name") .endpoint("https://container.s3.amazonaws.com/name")
.addHeader("Expect", "100-continue")
.addHeader("Host", "container.s3.amazonaws.com") .addHeader("Host", "container.s3.amazonaws.com")
.addHeader("Date", "Thu, 05 Jun 2008 16:38:19 GMT") .addHeader("Date", "Thu, 05 Jun 2008 16:38:19 GMT")
.addHeader("Authorization", "AWS identity:j9Dy/lmmvlCKjA4lkqZenLxMkR4=").build(); .addHeader("Authorization", "AWS identity:j9Dy/lmmvlCKjA4lkqZenLxMkR4=").build();
@ -98,6 +99,7 @@ public class S3BlobSignerExpectTest extends BaseBlobSignerExpectTest {
protected HttpRequest putBlobWithTime() { protected HttpRequest putBlobWithTime() {
return HttpRequest.builder().method("PUT") return HttpRequest.builder().method("PUT")
.endpoint("https://container.s3.amazonaws.com/name") .endpoint("https://container.s3.amazonaws.com/name")
.addHeader("Expect", "100-continue")
.addHeader("Host", "container.s3.amazonaws.com") .addHeader("Host", "container.s3.amazonaws.com")
.addHeader("Date", "Thu, 05 Jun 2008 16:38:19 GMT") .addHeader("Date", "Thu, 05 Jun 2008 16:38:19 GMT")
.addHeader("Authorization", "AWS identity:0uvBv1wEskuhFHYJF/L6kEV9A7o=").build(); .addHeader("Authorization", "AWS identity:0uvBv1wEskuhFHYJF/L6kEV9A7o=").build();

View File

@ -18,6 +18,8 @@
*/ */
package org.jclouds.openstack.swift; package org.jclouds.openstack.swift;
import static com.google.common.net.HttpHeaders.EXPECT;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -196,6 +198,7 @@ public interface CommonSwiftAsyncClient {
@Named("PutObject") @Named("PutObject")
@PUT @PUT
@Path("/{container}/{name}") @Path("/{container}/{name}")
@Headers(keys = EXPECT, values = "100-continue")
@ResponseParser(ParseETagHeader.class) @ResponseParser(ParseETagHeader.class)
ListenableFuture<String> putObject(@PathParam("container") String container, ListenableFuture<String> putObject(@PathParam("container") String container,
@PathParam("name") @ParamParser(ObjectName.class) @BinderParam(BindSwiftObjectMetadataToRequest.class) SwiftObject object); @PathParam("name") @ParamParser(ObjectName.class) @BinderParam(BindSwiftObjectMetadataToRequest.class) SwiftObject object);

View File

@ -78,6 +78,7 @@ public class SwiftBlobSignerExpectTest extends BaseBlobSignerExpectTest {
protected HttpRequest putBlob() { protected HttpRequest putBlob() {
return HttpRequest.builder().method("PUT") return HttpRequest.builder().method("PUT")
.endpoint("http://storage/container/name") .endpoint("http://storage/container/name")
.addHeader("Expect", "100-continue")
.addHeader("X-Auth-Token", "testtoken").build(); .addHeader("X-Auth-Token", "testtoken").build();
} }
@ -85,6 +86,7 @@ public class SwiftBlobSignerExpectTest extends BaseBlobSignerExpectTest {
protected HttpRequest putBlobWithTime() { protected HttpRequest putBlobWithTime() {
return HttpRequest.builder().method("PUT") return HttpRequest.builder().method("PUT")
.endpoint("http://storage/container/name?temp_url_sig=e894c60fa1284cc575cf22d7786bab07b8c33610&temp_url_expires=123456792") .endpoint("http://storage/container/name?temp_url_sig=e894c60fa1284cc575cf22d7786bab07b8c33610&temp_url_expires=123456792")
.addHeader("Expect", "100-continue")
.build(); .build();
} }

View File

@ -72,13 +72,16 @@ public class SwiftKeystoneBlobSignerExpectTest extends BaseBlobSignerExpectTest
protected HttpRequest putBlob() { protected HttpRequest putBlob() {
return HttpRequest.builder().method("PUT") return HttpRequest.builder().method("PUT")
.endpoint("https://objects.jclouds.org/v1.0/40806637803162/container/name") .endpoint("https://objects.jclouds.org/v1.0/40806637803162/container/name")
.addHeader("Expect", "100-continue")
.addHeader("X-Auth-Token", "Auth_4f173437e4b013bee56d1007").build(); .addHeader("X-Auth-Token", "Auth_4f173437e4b013bee56d1007").build();
} }
@Override @Override
protected HttpRequest putBlobWithTime() { protected HttpRequest putBlobWithTime() {
return HttpRequest.builder().method("PUT") return HttpRequest.builder().method("PUT")
.endpoint("https://objects.jclouds.org/v1.0/40806637803162/container/name?temp_url_sig=72e5f6ebafab2b3da0586198797e58fb7478211e&temp_url_expires=123456792").build(); .endpoint("https://objects.jclouds.org/v1.0/40806637803162/container/name?temp_url_sig=72e5f6ebafab2b3da0586198797e58fb7478211e&temp_url_expires=123456792")
.addHeader("Expect", "100-continue")
.build();
} }
@Override @Override

View File

@ -28,6 +28,7 @@ import java.net.URI;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import org.jclouds.io.Payload; import org.jclouds.io.Payload;
import org.jclouds.javax.annotation.Nullable; import org.jclouds.javax.annotation.Nullable;
@ -36,6 +37,7 @@ import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper; import com.google.common.base.Objects.ToStringHelper;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps; import com.google.common.collect.Multimaps;
@ -47,6 +49,9 @@ import com.google.common.collect.Multimaps;
*/ */
public class HttpRequest extends HttpMessage { public class HttpRequest extends HttpMessage {
public static final Set<String> NON_PAYLOAD_METHODS = ImmutableSet
.of("OPTIONS", "GET", "HEAD", "DELETE", "TRACE", "CONNECT");
public static Builder<?> builder() { public static Builder<?> builder() {
return new ConcreteBuilder(); return new ConcreteBuilder();
} }

View File

@ -63,7 +63,6 @@ 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;
@ -227,18 +226,14 @@ public class JavaUrlHttpCommandExecutorService extends BaseHttpCommandExecutorSe
} }
protected void writeNothing(HttpURLConnection connection) { protected void writeNothing(HttpURLConnection connection) {
connection.setRequestProperty(CONTENT_LENGTH, "0"); if (!HttpRequest.NON_PAYLOAD_METHODS.contains(connection.getRequestMethod())) {
// for some reason POST/PUT undoes the content length header above. connection.setRequestProperty(CONTENT_LENGTH, "0");
if (ImmutableSet.of("POST", "PUT").contains(connection.getRequestMethod())) {
connection.setFixedLengthStreamingMode(0);
connection.setDoOutput(true);
} }
} }
void writePayloadToConnection(Payload payload, HttpURLConnection connection) throws IOException { void writePayloadToConnection(Payload payload, HttpURLConnection connection) throws IOException {
Long length = payload.getContentMetadata().getContentLength(); Long length = payload.getContentMetadata().getContentLength();
connection.setRequestProperty(CONTENT_LENGTH, length.toString()); connection.setRequestProperty(CONTENT_LENGTH, length.toString());
connection.setRequestProperty("Expect", "100-continue");
connection.setFixedLengthStreamingMode(length.intValue()); connection.setFixedLengthStreamingMode(length.intValue());
connection.setDoOutput(true); connection.setDoOutput(true);
CountingOutputStream out = new CountingOutputStream(connection.getOutputStream()); CountingOutputStream out = new CountingOutputStream(connection.getOutputStream());

View File

@ -200,10 +200,13 @@ public class RestAnnotationProcessor implements Function<Invocation, HttpRequest
throw new NoSuchElementException(format("no endpoint found for %s", invocation)); throw new NoSuchElementException(format("no endpoint found for %s", invocation));
GeneratedHttpRequest.Builder requestBuilder = GeneratedHttpRequest.builder().invocation(invocation) GeneratedHttpRequest.Builder requestBuilder = GeneratedHttpRequest.builder().invocation(invocation)
.caller(caller); .caller(caller);
String requestMethod = null;
if (r != null) { if (r != null) {
requestMethod = r.getMethod();
requestBuilder.fromHttpRequest(r); requestBuilder.fromHttpRequest(r);
} else { } else {
requestBuilder.method(tryFindHttpMethod(invocation.getInvokable()).get()); requestMethod = tryFindHttpMethod(invocation.getInvokable()).get();
requestBuilder.method(requestMethod);
} }
requestBuilder.filters(getFiltersIfAnnotated(invocation)); requestBuilder.filters(getFiltersIfAnnotated(invocation));
@ -286,7 +289,7 @@ public class RestAnnotationProcessor implements Function<Invocation, HttpRequest
payload = new MultipartForm(MultipartForm.BOUNDARY, parts); payload = new MultipartForm(MultipartForm.BOUNDARY, parts);
} else if (formParams.size() > 0) { } else if (formParams.size() > 0) {
payload = Payloads.newUrlEncodedFormPayload(transformValues(formParams, NullableToStringFunction.INSTANCE)); payload = Payloads.newUrlEncodedFormPayload(transformValues(formParams, NullableToStringFunction.INSTANCE));
} else if (headers.containsKey(CONTENT_TYPE)) { } else if (headers.containsKey(CONTENT_TYPE) && !HttpRequest.NON_PAYLOAD_METHODS.contains(requestMethod)) {
if (payload == null) if (payload == null)
payload = Payloads.newByteArrayPayload(new byte[] {}); payload = Payloads.newByteArrayPayload(new byte[] {});
payload.getContentMetadata().setContentType(get(headers.get(CONTENT_TYPE), 0)); payload.getContentMetadata().setContentType(get(headers.get(CONTENT_TYPE), 0));

View File

@ -25,13 +25,13 @@ import javax.ws.rs.Consumes;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import org.jclouds.Fallbacks.NullOnNotFoundOr404; import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.dynect.v3.domain.Job; import org.jclouds.dynect.v3.domain.Job;
import org.jclouds.dynect.v3.features.RecordAsyncApi; import org.jclouds.dynect.v3.features.RecordAsyncApi;
import org.jclouds.dynect.v3.features.SessionAsyncApi; import org.jclouds.dynect.v3.features.SessionAsyncApi;
import org.jclouds.dynect.v3.features.ZoneAsyncApi; import org.jclouds.dynect.v3.features.ZoneAsyncApi;
import org.jclouds.dynect.v3.filters.AlwaysAddContentType;
import org.jclouds.dynect.v3.filters.SessionManager; import org.jclouds.dynect.v3.filters.SessionManager;
import org.jclouds.rest.annotations.Delegate; import org.jclouds.rest.annotations.Delegate;
import org.jclouds.rest.annotations.Fallback; import org.jclouds.rest.annotations.Fallback;
@ -55,8 +55,7 @@ public interface DynECTAsyncApi {
@Named("GetJob") @Named("GetJob")
@GET @GET
@Path("/Job/{jobId}") @Path("/Job/{jobId}")
@Produces(APPLICATION_JSON) @RequestFilters({ AlwaysAddContentType.class, SessionManager.class })
@RequestFilters(SessionManager.class)
@Headers(keys = "API-Version", values = "{jclouds.api-version}") @Headers(keys = "API-Version", values = "{jclouds.api-version}")
@Fallback(NullOnNotFoundOr404.class) @Fallback(NullOnNotFoundOr404.class)
@Consumes(APPLICATION_JSON) @Consumes(APPLICATION_JSON)

View File

@ -19,7 +19,6 @@
package org.jclouds.dynect.v3.features; package org.jclouds.dynect.v3.features;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import static org.jclouds.http.Uris.uriBuilder; import static org.jclouds.http.Uris.uriBuilder;
import java.net.URI; import java.net.URI;
@ -29,7 +28,6 @@ import javax.inject.Named;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import org.jclouds.Fallbacks.NullOnNotFoundOr404; import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.dynect.v3.DynECTExceptions.JobStillRunningException; import org.jclouds.dynect.v3.DynECTExceptions.JobStillRunningException;
@ -44,6 +42,7 @@ import org.jclouds.dynect.v3.domain.rdata.NSData;
import org.jclouds.dynect.v3.domain.rdata.PTRData; import org.jclouds.dynect.v3.domain.rdata.PTRData;
import org.jclouds.dynect.v3.domain.rdata.SRVData; import org.jclouds.dynect.v3.domain.rdata.SRVData;
import org.jclouds.dynect.v3.domain.rdata.TXTData; import org.jclouds.dynect.v3.domain.rdata.TXTData;
import org.jclouds.dynect.v3.filters.AlwaysAddContentType;
import org.jclouds.dynect.v3.filters.SessionManager; import org.jclouds.dynect.v3.filters.SessionManager;
import org.jclouds.dynect.v3.functions.ToRecordIds; import org.jclouds.dynect.v3.functions.ToRecordIds;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
@ -66,10 +65,8 @@ import com.google.common.util.concurrent.ListenableFuture;
* href="https://manage.dynect.net/help/docs/api2/rest/resources/AllRecord.html">doc</a> * href="https://manage.dynect.net/help/docs/api2/rest/resources/AllRecord.html">doc</a>
* @author Adrian Cole * @author Adrian Cole
*/ */
// required for all calls
@Produces(APPLICATION_JSON)
@Headers(keys = "API-Version", values = "{jclouds.api-version}") @Headers(keys = "API-Version", values = "{jclouds.api-version}")
@RequestFilters(SessionManager.class) @RequestFilters({ AlwaysAddContentType.class, SessionManager.class })
public interface RecordAsyncApi { public interface RecordAsyncApi {
/** /**

View File

@ -18,22 +18,21 @@
*/ */
package org.jclouds.dynect.v3.features; package org.jclouds.dynect.v3.features;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import javax.inject.Named; import javax.inject.Named;
import javax.ws.rs.DELETE; import javax.ws.rs.DELETE;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam; import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST; import javax.ws.rs.POST;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import org.jclouds.dynect.v3.DynECTFallbacks.FalseOn400; import org.jclouds.dynect.v3.DynECTFallbacks.FalseOn400;
import org.jclouds.dynect.v3.domain.Session; import org.jclouds.dynect.v3.domain.Session;
import org.jclouds.dynect.v3.domain.SessionCredentials; import org.jclouds.dynect.v3.domain.SessionCredentials;
import org.jclouds.dynect.v3.filters.AlwaysAddContentType;
import org.jclouds.rest.annotations.BinderParam; import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.Fallback; import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.Headers; import org.jclouds.rest.annotations.Headers;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson; import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.binders.BindToJsonPayload; import org.jclouds.rest.binders.BindToJsonPayload;
@ -47,10 +46,9 @@ import com.google.common.util.concurrent.ListenableFuture;
* @see <a href="https://manage.dynect.net/help/docs/api2/rest/" /> * @see <a href="https://manage.dynect.net/help/docs/api2/rest/" />
* @author Adrian Cole * @author Adrian Cole
*/ */
// required for all calls
@Produces(APPLICATION_JSON)
@Headers(keys = "API-Version", values = "{jclouds.api-version}") @Headers(keys = "API-Version", values = "{jclouds.api-version}")
@Path("/Session") @Path("/Session")
@RequestFilters(AlwaysAddContentType.class)
public interface SessionAsyncApi { public interface SessionAsyncApi {
/** /**

View File

@ -31,12 +31,13 @@ import javax.ws.rs.PathParam;
import javax.ws.rs.Produces; import javax.ws.rs.Produces;
import org.jclouds.Fallbacks.NullOnNotFoundOr404; import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.dynect.v3.DynECTExceptions.TargetExistsException;
import org.jclouds.dynect.v3.DynECTExceptions.JobStillRunningException; import org.jclouds.dynect.v3.DynECTExceptions.JobStillRunningException;
import org.jclouds.dynect.v3.DynECTExceptions.TargetExistsException;
import org.jclouds.dynect.v3.domain.CreatePrimaryZone; import org.jclouds.dynect.v3.domain.CreatePrimaryZone;
import org.jclouds.dynect.v3.domain.CreatePrimaryZone.ToFQDN; import org.jclouds.dynect.v3.domain.CreatePrimaryZone.ToFQDN;
import org.jclouds.dynect.v3.domain.Job; import org.jclouds.dynect.v3.domain.Job;
import org.jclouds.dynect.v3.domain.Zone; import org.jclouds.dynect.v3.domain.Zone;
import org.jclouds.dynect.v3.filters.AlwaysAddContentType;
import org.jclouds.dynect.v3.filters.SessionManager; import org.jclouds.dynect.v3.filters.SessionManager;
import org.jclouds.dynect.v3.functions.ExtractZoneNames; import org.jclouds.dynect.v3.functions.ExtractZoneNames;
import org.jclouds.rest.annotations.BinderParam; import org.jclouds.rest.annotations.BinderParam;
@ -60,10 +61,8 @@ import com.google.common.util.concurrent.ListenableFuture;
* href="https://manage.dynect.net/help/docs/api2/rest/resources/Zone.html">doc</a> * href="https://manage.dynect.net/help/docs/api2/rest/resources/Zone.html">doc</a>
* @author Adrian Cole * @author Adrian Cole
*/ */
// required for all calls
@Produces(APPLICATION_JSON)
@Headers(keys = "API-Version", values = "{jclouds.api-version}") @Headers(keys = "API-Version", values = "{jclouds.api-version}")
@RequestFilters(SessionManager.class) @RequestFilters({ AlwaysAddContentType.class, SessionManager.class })
public interface ZoneAsyncApi { public interface ZoneAsyncApi {
/** /**
@ -102,6 +101,7 @@ public interface ZoneAsyncApi {
*/ */
@Named("CreatePrimaryZone") @Named("CreatePrimaryZone")
@POST @POST
@Produces(APPLICATION_JSON)
@Payload("%7B\"rname\":\"{contact}\",\"serial_style\":\"increment\",\"ttl\":3600%7D") @Payload("%7B\"rname\":\"{contact}\",\"serial_style\":\"increment\",\"ttl\":3600%7D")
@Path("/Zone/{fqdn}") @Path("/Zone/{fqdn}")
@SelectJson("data") @SelectJson("data")
@ -132,8 +132,9 @@ public interface ZoneAsyncApi {
*/ */
@Named("PublishZone") @Named("PublishZone")
@PUT @PUT
@Payload("{\"publish\":true}")
@Path("/Zone/{fqdn}") @Path("/Zone/{fqdn}")
@Produces(APPLICATION_JSON)
@Payload("{\"publish\":true}")
@SelectJson("data") @SelectJson("data")
ListenableFuture<Zone> publish(@PathParam("fqdn") String fqdn) throws JobStillRunningException; ListenableFuture<Zone> publish(@PathParam("fqdn") String fqdn) throws JobStillRunningException;
@ -143,6 +144,7 @@ public interface ZoneAsyncApi {
@Named("FreezeZone") @Named("FreezeZone")
@PUT @PUT
@Path("/Zone/{fqdn}") @Path("/Zone/{fqdn}")
@Produces(APPLICATION_JSON)
@Payload("{\"freeze\":true}") @Payload("{\"freeze\":true}")
@Consumes(APPLICATION_JSON) @Consumes(APPLICATION_JSON)
ListenableFuture<Job> freeze(@PathParam("fqdn") String fqdn) throws JobStillRunningException; ListenableFuture<Job> freeze(@PathParam("fqdn") String fqdn) throws JobStillRunningException;
@ -153,6 +155,7 @@ public interface ZoneAsyncApi {
@Named("ThawZone") @Named("ThawZone")
@PUT @PUT
@Path("/Zone/{fqdn}") @Path("/Zone/{fqdn}")
@Produces(APPLICATION_JSON)
@Payload("{\"thaw\":true}") @Payload("{\"thaw\":true}")
@Consumes(APPLICATION_JSON) @Consumes(APPLICATION_JSON)
ListenableFuture<Job> thaw(@PathParam("fqdn") String fqdn) throws JobStillRunningException; ListenableFuture<Job> thaw(@PathParam("fqdn") String fqdn) throws JobStillRunningException;

View File

@ -0,0 +1,42 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.dynect.v3.filters;
import static com.google.common.net.HttpHeaders.CONTENT_TYPE;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import static org.jclouds.http.HttpRequest.NON_PAYLOAD_METHODS;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpRequestFilter;
/**
*
* DynECT requires Content-Type even on GET requests.
*
* @author Adrian Cole
*/
public final class AlwaysAddContentType implements HttpRequestFilter {
@Override
public HttpRequest filter(HttpRequest request) throws HttpException {
if (NON_PAYLOAD_METHODS.contains(request.getMethod()))
return request.toBuilder().replaceHeader(CONTENT_TYPE, APPLICATION_JSON).build();
return request;
}
}

View File

@ -56,7 +56,7 @@ public class GetJobRedirectionRetryHandler extends RedirectionRetryHandler {
if (location != null && location.indexOf("Job") != -1) { if (location != null && location.indexOf("Job") != -1) {
HttpRequest getRequest = command.getCurrentRequest().toBuilder() HttpRequest getRequest = command.getCurrentRequest().toBuilder()
.method("GET") .method("GET")
.payload(emptyPayload).build(); .payload((Payload) null).build();
command.setCurrentRequest(getRequest); command.setCurrentRequest(getRequest);
} }
return super.shouldRetryRequest(command, response); return super.shouldRetryRequest(command, response);

View File

@ -19,17 +19,16 @@
package org.jclouds.dynect.v3; package org.jclouds.dynect.v3;
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor; import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
import static org.jclouds.Constants.PROPERTY_CONNECTION_TIMEOUT;
import static org.jclouds.Constants.PROPERTY_MAX_RETRIES; import static org.jclouds.Constants.PROPERTY_MAX_RETRIES;
import static org.jclouds.Constants.PROPERTY_SO_TIMEOUT;
import java.io.IOException; import java.io.IOException;
import java.util.Properties; import java.util.Properties;
import java.util.Set;
import org.jclouds.ContextBuilder; import org.jclouds.ContextBuilder;
import org.jclouds.concurrent.config.ExecutorServiceModule; import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.dynect.v3.DynECTExceptions.TargetExistsException;
import org.jclouds.dynect.v3.DynECTExceptions.JobStillRunningException; import org.jclouds.dynect.v3.DynECTExceptions.JobStillRunningException;
import org.jclouds.dynect.v3.DynECTExceptions.TargetExistsException;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
@ -43,18 +42,18 @@ import com.google.mockwebserver.MockWebServer;
*/ */
@Test(singleThreaded = true) @Test(singleThreaded = true)
public class DynectApiMockTest { public class DynectApiMockTest {
private static final Set<Module> modules = ImmutableSet.<Module> of(
new ExecutorServiceModule(sameThreadExecutor(), sameThreadExecutor()));
static DynECTApi mockDynectApi(String uri) { static DynECTApi mockDynectApi(String uri) {
Properties overrides = new Properties(); Properties overrides = new Properties();
overrides.setProperty(PROPERTY_CONNECTION_TIMEOUT, "1000");
// prevent expect-100 bug http://code.google.com/p/mockwebserver/issues/detail?id=6
overrides.setProperty(PROPERTY_SO_TIMEOUT, "0");
overrides.setProperty(PROPERTY_MAX_RETRIES, "1"); overrides.setProperty(PROPERTY_MAX_RETRIES, "1");
return ContextBuilder.newBuilder("dynect") return ContextBuilder.newBuilder("dynect")
.credentials("jclouds:joe", "letmein") .credentials("jclouds:joe", "letmein")
.endpoint(uri) .endpoint(uri)
.overrides(overrides) .overrides(overrides)
.modules(ImmutableSet.<Module> of(new ExecutorServiceModule(sameThreadExecutor(), sameThreadExecutor()))) .modules(modules)
.build(DynECTApiMetadata.CONTEXT_TOKEN).getApi(); .build(DynECTApiMetadata.CONTEXT_TOKEN).getApi();
} }

View File

@ -18,6 +18,7 @@
*/ */
package org.jclouds.dynect.v3.features; package org.jclouds.dynect.v3.features;
import static com.google.common.net.HttpHeaders.CONTENT_TYPE;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON; import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import static org.jclouds.dynect.v3.domain.RecordId.recordIdBuilder; import static org.jclouds.dynect.v3.domain.RecordId.recordIdBuilder;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
@ -49,8 +50,8 @@ public class RecordApiExpectTest extends BaseDynECTApiExpectTest {
HttpRequest getSOA = HttpRequest.builder().method("GET") HttpRequest getSOA = HttpRequest.builder().method("GET")
.endpoint("https://api2.dynect.net/REST/SOARecord/adrianc.zone.dynecttest.jclouds.org/adrianc.zone.dynecttest.jclouds.org/50976579") .endpoint("https://api2.dynect.net/REST/SOARecord/adrianc.zone.dynecttest.jclouds.org/adrianc.zone.dynecttest.jclouds.org/50976579")
.addHeader("API-Version", "3.3.8") .addHeader("API-Version", "3.3.8")
.addHeader("Auth-Token", authToken) .addHeader(CONTENT_TYPE, APPLICATION_JSON)
.payload(emptyJsonPayload()).build(); .addHeader("Auth-Token", authToken).build();
HttpResponse soaResponse = HttpResponse.builder().statusCode(200) HttpResponse soaResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/get_record_soa.json", APPLICATION_JSON)).build(); .payload(payloadFromResourceWithContentType("/get_record_soa.json", APPLICATION_JSON)).build();
@ -75,8 +76,8 @@ public class RecordApiExpectTest extends BaseDynECTApiExpectTest {
HttpRequest getAAAA = HttpRequest.builder().method("GET") HttpRequest getAAAA = HttpRequest.builder().method("GET")
.endpoint("https://api2.dynect.net/REST/AAAARecord/adrianc.zone.dynecttest.jclouds.org/adrianc.zone.dynecttest.jclouds.org/50976579") .endpoint("https://api2.dynect.net/REST/AAAARecord/adrianc.zone.dynecttest.jclouds.org/adrianc.zone.dynecttest.jclouds.org/50976579")
.addHeader("API-Version", "3.3.8") .addHeader("API-Version", "3.3.8")
.addHeader("Auth-Token", authToken) .addHeader(CONTENT_TYPE, APPLICATION_JSON)
.payload(emptyJsonPayload()).build(); .addHeader("Auth-Token", authToken).build();
HttpResponse aaaaResponse = HttpResponse.builder().statusCode(200) HttpResponse aaaaResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/get_record_aaaa.json", APPLICATION_JSON)).build(); .payload(payloadFromResourceWithContentType("/get_record_aaaa.json", APPLICATION_JSON)).build();
@ -101,8 +102,8 @@ public class RecordApiExpectTest extends BaseDynECTApiExpectTest {
HttpRequest getA = HttpRequest.builder().method("GET") HttpRequest getA = HttpRequest.builder().method("GET")
.endpoint("https://api2.dynect.net/REST/ARecord/adrianc.zone.dynecttest.jclouds.org/adrianc.zone.dynecttest.jclouds.org/50976579") .endpoint("https://api2.dynect.net/REST/ARecord/adrianc.zone.dynecttest.jclouds.org/adrianc.zone.dynecttest.jclouds.org/50976579")
.addHeader("API-Version", "3.3.8") .addHeader("API-Version", "3.3.8")
.addHeader("Auth-Token", authToken) .addHeader(CONTENT_TYPE, APPLICATION_JSON)
.payload(emptyJsonPayload()).build(); .addHeader("Auth-Token", authToken).build();
HttpResponse aResponse = HttpResponse.builder().statusCode(200) HttpResponse aResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/get_record_a.json", APPLICATION_JSON)).build(); .payload(payloadFromResourceWithContentType("/get_record_a.json", APPLICATION_JSON)).build();
@ -127,8 +128,8 @@ public class RecordApiExpectTest extends BaseDynECTApiExpectTest {
HttpRequest getCNAME = HttpRequest.builder().method("GET") HttpRequest getCNAME = HttpRequest.builder().method("GET")
.endpoint("https://api2.dynect.net/REST/CNAMERecord/adrianc.zone.dynecttest.jclouds.org/adrianc.zone.dynecttest.jclouds.org/50976579") .endpoint("https://api2.dynect.net/REST/CNAMERecord/adrianc.zone.dynecttest.jclouds.org/adrianc.zone.dynecttest.jclouds.org/50976579")
.addHeader("API-Version", "3.3.8") .addHeader("API-Version", "3.3.8")
.addHeader("Auth-Token", authToken) .addHeader(CONTENT_TYPE, APPLICATION_JSON)
.payload(emptyJsonPayload()).build(); .addHeader("Auth-Token", authToken).build();
HttpResponse cnameResponse = HttpResponse.builder().statusCode(200) HttpResponse cnameResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/get_record_cname.json", APPLICATION_JSON)).build(); .payload(payloadFromResourceWithContentType("/get_record_cname.json", APPLICATION_JSON)).build();
@ -153,8 +154,8 @@ public class RecordApiExpectTest extends BaseDynECTApiExpectTest {
HttpRequest getMX = HttpRequest.builder().method("GET") HttpRequest getMX = HttpRequest.builder().method("GET")
.endpoint("https://api2.dynect.net/REST/MXRecord/adrianc.zone.dynecttest.jclouds.org/adrianc.zone.dynecttest.jclouds.org/50976579") .endpoint("https://api2.dynect.net/REST/MXRecord/adrianc.zone.dynecttest.jclouds.org/adrianc.zone.dynecttest.jclouds.org/50976579")
.addHeader("API-Version", "3.3.8") .addHeader("API-Version", "3.3.8")
.addHeader("Auth-Token", authToken) .addHeader(CONTENT_TYPE, APPLICATION_JSON)
.payload(emptyJsonPayload()).build(); .addHeader("Auth-Token", authToken).build();
HttpResponse mxResponse = HttpResponse.builder().statusCode(200) HttpResponse mxResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/get_record_mx.json", APPLICATION_JSON)).build(); .payload(payloadFromResourceWithContentType("/get_record_mx.json", APPLICATION_JSON)).build();
@ -179,8 +180,8 @@ public class RecordApiExpectTest extends BaseDynECTApiExpectTest {
HttpRequest getNS = HttpRequest.builder().method("GET") HttpRequest getNS = HttpRequest.builder().method("GET")
.endpoint("https://api2.dynect.net/REST/NSRecord/adrianc.zone.dynecttest.jclouds.org/adrianc.zone.dynecttest.jclouds.org/50976579") .endpoint("https://api2.dynect.net/REST/NSRecord/adrianc.zone.dynecttest.jclouds.org/adrianc.zone.dynecttest.jclouds.org/50976579")
.addHeader("API-Version", "3.3.8") .addHeader("API-Version", "3.3.8")
.addHeader("Auth-Token", authToken) .addHeader(CONTENT_TYPE, APPLICATION_JSON)
.payload(emptyJsonPayload()).build(); .addHeader("Auth-Token", authToken).build();
HttpResponse nsResponse = HttpResponse.builder().statusCode(200) HttpResponse nsResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/get_record_ns.json", APPLICATION_JSON)).build(); .payload(payloadFromResourceWithContentType("/get_record_ns.json", APPLICATION_JSON)).build();
@ -205,8 +206,8 @@ public class RecordApiExpectTest extends BaseDynECTApiExpectTest {
HttpRequest getPTR = HttpRequest.builder().method("GET") HttpRequest getPTR = HttpRequest.builder().method("GET")
.endpoint("https://api2.dynect.net/REST/PTRRecord/adrianc.zone.dynecttest.jclouds.org/adrianc.zone.dynecttest.jclouds.org/50976579") .endpoint("https://api2.dynect.net/REST/PTRRecord/adrianc.zone.dynecttest.jclouds.org/adrianc.zone.dynecttest.jclouds.org/50976579")
.addHeader("API-Version", "3.3.8") .addHeader("API-Version", "3.3.8")
.addHeader("Auth-Token", authToken) .addHeader(CONTENT_TYPE, APPLICATION_JSON)
.payload(emptyJsonPayload()).build(); .addHeader("Auth-Token", authToken).build();
HttpResponse ptrResponse = HttpResponse.builder().statusCode(200) HttpResponse ptrResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/get_record_ptr.json", APPLICATION_JSON)).build(); .payload(payloadFromResourceWithContentType("/get_record_ptr.json", APPLICATION_JSON)).build();
@ -242,8 +243,8 @@ public class RecordApiExpectTest extends BaseDynECTApiExpectTest {
HttpRequest getSRV = HttpRequest.builder().method("GET") HttpRequest getSRV = HttpRequest.builder().method("GET")
.endpoint("https://api2.dynect.net/REST/SRVRecord/adrianc.zone.dynecttest.jclouds.org/adrianc.zone.dynecttest.jclouds.org/50976579") .endpoint("https://api2.dynect.net/REST/SRVRecord/adrianc.zone.dynecttest.jclouds.org/adrianc.zone.dynecttest.jclouds.org/50976579")
.addHeader("API-Version", "3.3.8") .addHeader("API-Version", "3.3.8")
.addHeader("Auth-Token", authToken) .addHeader(CONTENT_TYPE, APPLICATION_JSON)
.payload(emptyJsonPayload()).build(); .addHeader("Auth-Token", authToken).build();
HttpResponse srvResponse = HttpResponse.builder().statusCode(200) HttpResponse srvResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/get_record_srv.json", APPLICATION_JSON)).build(); .payload(payloadFromResourceWithContentType("/get_record_srv.json", APPLICATION_JSON)).build();
@ -263,8 +264,8 @@ public class RecordApiExpectTest extends BaseDynECTApiExpectTest {
HttpRequest getTXT = HttpRequest.builder().method("GET") HttpRequest getTXT = HttpRequest.builder().method("GET")
.endpoint("https://api2.dynect.net/REST/TXTRecord/adrianc.zone.dynecttest.jclouds.org/adrianc.zone.dynecttest.jclouds.org/50976579") .endpoint("https://api2.dynect.net/REST/TXTRecord/adrianc.zone.dynecttest.jclouds.org/adrianc.zone.dynecttest.jclouds.org/50976579")
.addHeader("API-Version", "3.3.8") .addHeader("API-Version", "3.3.8")
.addHeader("Auth-Token", authToken) .addHeader(CONTENT_TYPE, APPLICATION_JSON)
.payload(emptyJsonPayload()).build(); .addHeader("Auth-Token", authToken).build();
HttpResponse txtResponse = HttpResponse.builder().statusCode(200) HttpResponse txtResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/get_record_txt.json", APPLICATION_JSON)).build(); .payload(payloadFromResourceWithContentType("/get_record_txt.json", APPLICATION_JSON)).build();
@ -289,8 +290,8 @@ public class RecordApiExpectTest extends BaseDynECTApiExpectTest {
HttpRequest list = HttpRequest.builder().method("GET") HttpRequest list = HttpRequest.builder().method("GET")
.endpoint("https://api2.dynect.net/REST/AllRecord/adrianc.zone.dynecttest.jclouds.org") .endpoint("https://api2.dynect.net/REST/AllRecord/adrianc.zone.dynecttest.jclouds.org")
.addHeader("API-Version", "3.3.8") .addHeader("API-Version", "3.3.8")
.addHeader("Auth-Token", authToken) .addHeader(CONTENT_TYPE, APPLICATION_JSON)
.payload(emptyJsonPayload()).build(); .addHeader("Auth-Token", authToken).build();
HttpResponse listResponse = HttpResponse.builder().statusCode(200) HttpResponse listResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/list_records.json", APPLICATION_JSON)).build(); .payload(payloadFromResourceWithContentType("/list_records.json", APPLICATION_JSON)).build();

View File

@ -18,6 +18,7 @@
*/ */
package org.jclouds.dynect.v3.features; package org.jclouds.dynect.v3.features;
import static com.google.common.net.HttpHeaders.CONTENT_TYPE;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON; import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertFalse;
@ -47,11 +48,10 @@ public class SessionApiExpectTest extends BaseDynECTApiExpectTest {
} }
HttpRequest isValid = HttpRequest.builder().method("GET") HttpRequest isValid = HttpRequest.builder().method("GET")
.endpoint("https://api2.dynect.net/REST/Session") .endpoint("https://api2.dynect.net/REST/Session")
.addHeader("API-Version", "3.3.8") .addHeader("API-Version", "3.3.8")
.addHeader("Auth-Token", authToken) .addHeader(CONTENT_TYPE, APPLICATION_JSON)
.payload(emptyJsonPayload()) .addHeader("Auth-Token", authToken).build();
.build();
HttpResponse validResponse = HttpResponse.builder().statusCode(200) HttpResponse validResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/session_valid.json", APPLICATION_JSON)).build(); .payload(payloadFromResourceWithContentType("/session_valid.json", APPLICATION_JSON)).build();
@ -70,11 +70,10 @@ public class SessionApiExpectTest extends BaseDynECTApiExpectTest {
} }
HttpRequest logout = HttpRequest.builder().method("DELETE") HttpRequest logout = HttpRequest.builder().method("DELETE")
.endpoint("https://api2.dynect.net/REST/Session") .endpoint("https://api2.dynect.net/REST/Session")
.addHeader("API-Version", "3.3.8") .addHeader("API-Version", "3.3.8")
.addHeader("Auth-Token", authToken) .addHeader(CONTENT_TYPE, APPLICATION_JSON)
.payload(emptyJsonPayload()) .addHeader("Auth-Token", authToken).build();
.build();
HttpResponse logoutResponse = HttpResponse.builder().statusCode(200) HttpResponse logoutResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/logout.json", APPLICATION_JSON)).build(); .payload(payloadFromResourceWithContentType("/logout.json", APPLICATION_JSON)).build();

View File

@ -19,6 +19,7 @@
package org.jclouds.dynect.v3.features; package org.jclouds.dynect.v3.features;
import static com.google.common.net.HttpHeaders.ACCEPT; import static com.google.common.net.HttpHeaders.ACCEPT;
import static com.google.common.net.HttpHeaders.CONTENT_TYPE;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON; import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull; import static org.testng.Assert.assertNull;
@ -40,11 +41,10 @@ import org.testng.annotations.Test;
@Test(groups = "unit", testName = "ZoneApiExpectTest") @Test(groups = "unit", testName = "ZoneApiExpectTest")
public class ZoneApiExpectTest extends BaseDynECTApiExpectTest { public class ZoneApiExpectTest extends BaseDynECTApiExpectTest {
HttpRequest get = HttpRequest.builder().method("GET") HttpRequest get = HttpRequest.builder().method("GET")
.endpoint("https://api2.dynect.net/REST/Zone/jclouds.org") .endpoint("https://api2.dynect.net/REST/Zone/jclouds.org")
.addHeader("API-Version", "3.3.8") .addHeader("API-Version", "3.3.8")
.addHeader("Auth-Token", authToken) .addHeader(CONTENT_TYPE, APPLICATION_JSON)
.payload(emptyJsonPayload()) .addHeader("Auth-Token", authToken).build();
.build();
HttpResponse getResponse = HttpResponse.builder().statusCode(200) HttpResponse getResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/get_zone.json", APPLICATION_JSON)).build(); .payload(payloadFromResourceWithContentType("/get_zone.json", APPLICATION_JSON)).build();
@ -83,11 +83,10 @@ public class ZoneApiExpectTest extends BaseDynECTApiExpectTest {
} }
HttpRequest list = HttpRequest.builder().method("GET") HttpRequest list = HttpRequest.builder().method("GET")
.endpoint("https://api2.dynect.net/REST/Zone") .endpoint("https://api2.dynect.net/REST/Zone")
.addHeader("API-Version", "3.3.8") .addHeader("API-Version", "3.3.8")
.addHeader("Auth-Token", authToken) .addHeader(CONTENT_TYPE, APPLICATION_JSON)
.payload(emptyJsonPayload()) .addHeader("Auth-Token", authToken).build();
.build();
HttpResponse listResponse = HttpResponse.builder().statusCode(200) HttpResponse listResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/list_zones.json", APPLICATION_JSON)).build(); .payload(payloadFromResourceWithContentType("/list_zones.json", APPLICATION_JSON)).build();
@ -99,12 +98,11 @@ public class ZoneApiExpectTest extends BaseDynECTApiExpectTest {
} }
HttpRequest deleteChanges = HttpRequest.builder().method("DELETE") HttpRequest deleteChanges = HttpRequest.builder().method("DELETE")
.endpoint("https://api2.dynect.net/REST/ZoneChanges/jclouds.org") .endpoint("https://api2.dynect.net/REST/ZoneChanges/jclouds.org")
.addHeader("API-Version", "3.3.8") .addHeader("API-Version", "3.3.8")
.addHeader(ACCEPT, APPLICATION_JSON) .addHeader(ACCEPT, APPLICATION_JSON)
.addHeader("Auth-Token", authToken) .addHeader(CONTENT_TYPE, APPLICATION_JSON)
.payload(emptyJsonPayload()) .addHeader("Auth-Token", authToken).build();
.build();
HttpResponse deleteChangesResponse = HttpResponse.builder().statusCode(200) HttpResponse deleteChangesResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/delete_zone_changes.json", APPLICATION_JSON)).build(); .payload(payloadFromResourceWithContentType("/delete_zone_changes.json", APPLICATION_JSON)).build();
@ -116,12 +114,11 @@ public class ZoneApiExpectTest extends BaseDynECTApiExpectTest {
} }
HttpRequest delete = HttpRequest.builder().method("DELETE") HttpRequest delete = HttpRequest.builder().method("DELETE")
.endpoint("https://api2.dynect.net/REST/Zone/jclouds.org") .endpoint("https://api2.dynect.net/REST/Zone/jclouds.org")
.addHeader("API-Version", "3.3.8") .addHeader("API-Version", "3.3.8")
.addHeader(ACCEPT, APPLICATION_JSON) .addHeader(ACCEPT, APPLICATION_JSON)
.addHeader("Auth-Token", authToken) .addHeader(CONTENT_TYPE, APPLICATION_JSON)
.payload(emptyJsonPayload()) .addHeader("Auth-Token", authToken).build();
.build();
HttpResponse deleteResponse = HttpResponse.builder().statusCode(200) HttpResponse deleteResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/delete_zone.json", APPLICATION_JSON)).build(); .payload(payloadFromResourceWithContentType("/delete_zone.json", APPLICATION_JSON)).build();

View File

@ -19,6 +19,7 @@
package org.jclouds.dynect.v3.handlers; package org.jclouds.dynect.v3.handlers;
import static com.google.common.net.HttpHeaders.ACCEPT; import static com.google.common.net.HttpHeaders.ACCEPT;
import static com.google.common.net.HttpHeaders.CONTENT_TYPE;
import static com.google.common.net.HttpHeaders.LOCATION; import static com.google.common.net.HttpHeaders.LOCATION;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON; import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
@ -54,9 +55,8 @@ public class GetJobRedirectionRetryHandlerExpectTest extends BaseDynECTApiExpect
.endpoint("https://api2.dynect.net/REST/Job/1234") .endpoint("https://api2.dynect.net/REST/Job/1234")
.addHeader("API-Version", "3.3.8") .addHeader("API-Version", "3.3.8")
.addHeader(ACCEPT, APPLICATION_JSON) .addHeader(ACCEPT, APPLICATION_JSON)
.addHeader("Auth-Token", authToken) .addHeader(CONTENT_TYPE, APPLICATION_JSON)
.payload(emptyJsonPayload()) .addHeader("Auth-Token", authToken).build();
.build();
HttpResponse success = HttpResponse.builder().statusCode(200) HttpResponse success = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/delete_zone.json", APPLICATION_JSON)).build(); .payload(payloadFromResourceWithContentType("/delete_zone.json", APPLICATION_JSON)).build();

View File

@ -57,12 +57,6 @@ public class BaseDynECTExpectTest<T> extends BaseRestApiExpectTest<T> {
} }
} }
public static Payload emptyJsonPayload() {
Payload p = Payloads.newByteArrayPayload(new byte[] {});
p.getContentMetadata().setContentType(APPLICATION_JSON);
return p;
}
public static Payload stringPayload(String json) { public static Payload stringPayload(String json) {
Payload p = Payloads.newPayload(json); Payload p = Payloads.newPayload(json);
p.getContentMetadata().setContentType(APPLICATION_JSON); p.getContentMetadata().setContentType(APPLICATION_JSON);

View File

@ -451,6 +451,7 @@
</property> </property>
</properties> </properties>
<systemPropertyVariables> <systemPropertyVariables>
<sun.net.http.allowRestrictedHeaders>true</sun.net.http.allowRestrictedHeaders>
<jclouds.wire.httpstream.url>${jclouds.wire.httpstream.url}</jclouds.wire.httpstream.url> <jclouds.wire.httpstream.url>${jclouds.wire.httpstream.url}</jclouds.wire.httpstream.url>
<jclouds.wire.httpstream.md5>${jclouds.wire.httpstream.md5}</jclouds.wire.httpstream.md5> <jclouds.wire.httpstream.md5>${jclouds.wire.httpstream.md5}</jclouds.wire.httpstream.md5>
</systemPropertyVariables> </systemPropertyVariables>

View File

@ -105,7 +105,7 @@ public class AWSS3AsyncClientTest extends S3AsyncClientTest<AWSS3AsyncClient> {
blobToS3Object.apply(BindBlobToMultipartFormTest.TEST_BLOB))); blobToS3Object.apply(BindBlobToMultipartFormTest.TEST_BLOB)));
assertRequestLineEquals(request, "PUT https://bucket." + url + "/hello HTTP/1.1"); assertRequestLineEquals(request, "PUT https://bucket." + url + "/hello HTTP/1.1");
assertNonPayloadHeadersEqual(request, "Host: bucket." + url + "\n"); assertNonPayloadHeadersEqual(request, "Expect: 100-continue\nHost: bucket." + url + "\n");
assertPayloadEquals(request, "hello", "text/plain", false); assertPayloadEquals(request, "hello", "text/plain", false);
assertResponseParserClassEquals(method, request, ParseETagHeader.class); assertResponseParserClassEquals(method, request, ParseETagHeader.class);

View File

@ -73,6 +73,7 @@ public class AWSS3ClientExpectTest extends BaseAWSS3ClientExpectTest {
HttpRequest.builder() HttpRequest.builder()
.method("PUT") .method("PUT")
.endpoint("https://test.s3-eu-west-1.amazonaws.com/test") .endpoint("https://test.s3-eu-west-1.amazonaws.com/test")
.addHeader("Expect", "100-continue")
.addHeader("x-amz-storage-class", "REDUCED_REDUNDANCY") .addHeader("x-amz-storage-class", "REDUCED_REDUNDANCY")
.addHeader("Host", "test.s3-eu-west-1.amazonaws.com") .addHeader("Host", "test.s3-eu-west-1.amazonaws.com")
.addHeader("Date", CONSTANT_DATE) .addHeader("Date", CONSTANT_DATE)

View File

@ -18,6 +18,8 @@
*/ */
package org.jclouds.azureblob; package org.jclouds.azureblob;
import static com.google.common.net.HttpHeaders.EXPECT;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
@ -217,6 +219,7 @@ public interface AzureBlobAsyncClient {
@Named("PutBlob") @Named("PutBlob")
@PUT @PUT
@Path("{container}/{name}") @Path("{container}/{name}")
@Headers(keys = EXPECT, values = "100-continue")
@ResponseParser(ParseETagHeader.class) @ResponseParser(ParseETagHeader.class)
ListenableFuture<String> putBlob( ListenableFuture<String> putBlob(
@PathParam("container") @ParamValidators(ContainerNameValidator.class) String container, @PathParam("container") @ParamValidators(ContainerNameValidator.class) String container,

View File

@ -97,7 +97,7 @@ public class AzureBlobRequestSignerTest extends BaseAsyncClientTest<AzureBlobAsy
assertRequestLineEquals(request, "PUT https://identity.blob.core.windows.net/container/name HTTP/1.1"); assertRequestLineEquals(request, "PUT https://identity.blob.core.windows.net/container/name HTTP/1.1");
assertNonPayloadHeadersEqual( assertNonPayloadHeadersEqual(
request, request,
"Authorization: SharedKeyLite identity:ssvK6ZB8GMqRcp1lBpY9vIzbLKL9Goxh7wZ2YhfHNzQ=\nDate: Thu, 05 Jun 2008 16:38:19 GMT\nx-ms-blob-type: BlockBlob\nx-ms-version: 2009-09-19\n"); "Authorization: SharedKeyLite identity:ssvK6ZB8GMqRcp1lBpY9vIzbLKL9Goxh7wZ2YhfHNzQ=\nDate: Thu, 05 Jun 2008 16:38:19 GMT\nExpect: 100-continue\nx-ms-blob-type: BlockBlob\nx-ms-version: 2009-09-19\n");
assertContentHeadersEqual(request, "text/plain", null, null, null, (long) 2l, new byte[] { 0, 2, 4, 8 }, new Date(1000)); assertContentHeadersEqual(request, "text/plain", null, null, null, (long) 2l, new byte[] { 0, 2, 4, 8 }, new Date(1000));
assertEquals(request.getFilters().size(), 0); assertEquals(request.getFilters().size(), 0);

View File

@ -75,6 +75,7 @@ public class HPCloudObjectStorageBlobSignerExpectTest extends BaseBlobSignerExpe
protected HttpRequest putBlob() { protected HttpRequest putBlob() {
return HttpRequest.builder().method("PUT") return HttpRequest.builder().method("PUT")
.endpoint("https://objects.jclouds.org/v1.0/40806637803162/container/name") .endpoint("https://objects.jclouds.org/v1.0/40806637803162/container/name")
.addHeader("Expect", "100-continue")
.addHeader("X-Auth-Token", "Auth_4f173437e4b013bee56d1007").build(); .addHeader("X-Auth-Token", "Auth_4f173437e4b013bee56d1007").build();
} }
@ -82,6 +83,7 @@ public class HPCloudObjectStorageBlobSignerExpectTest extends BaseBlobSignerExpe
protected HttpRequest putBlobWithTime() { protected HttpRequest putBlobWithTime() {
return HttpRequest.builder().method("PUT") return HttpRequest.builder().method("PUT")
.endpoint("https://objects.jclouds.org/v1.0/40806637803162/container/name?temp_url_sig=40806637803162%3Aidentity%3Ac90269245ab0a316d5ea5e654d4c2a975fb4bf77&temp_url_expires=123456792") .endpoint("https://objects.jclouds.org/v1.0/40806637803162/container/name?temp_url_sig=40806637803162%3Aidentity%3Ac90269245ab0a316d5ea5e654d4c2a975fb4bf77&temp_url_expires=123456792")
.addHeader("Expect", "100-continue")
.build(); .build();
} }