GetBucketLocation should use path-style requests.

When making a GetBucketLocation request, Amazon may route the request
to the bucket region. When making it with v4 signer, the request may
fail because of the region mismatch. Concretely, a request to
test.s3.amazonaws.com may resolve to s3-us-west-2-w.amazonaws.com. The
request itself is prepared for the us-east-1 region (s3.amazonaws.com
endpoint), but then fails when the DNS resolution points to a
us-west-2 endpoint.

Bucket-in-path works around this for the GetBucketLocation requests.
That means that every GetBucketLocation request will be of the form:
https://s3.amazonaws.com/{bucket}?location. This ensures that jclouds
requests will not be subjected to Amazon's routing/DNS pointers.

Fixes: JCLOUDS-1213
This commit is contained in:
Timur Alperovich 2017-01-11 18:14:57 -08:00
parent 47350e354c
commit 98ea917477
3 changed files with 8 additions and 11 deletions

View File

@ -533,10 +533,10 @@ public interface S3Client extends Closeable {
@Named("GetBucketLocation")
@GET
@QueryParams(keys = "location")
@Path("/")
@Path("/{bucket}")
@Endpoint(Bucket.class)
@XMLResponseParser(LocationConstraintHandler.class)
String getBucketLocation(@Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators(
String getBucketLocation(@Bucket @PathParam("bucket") @ParamValidators(
BucketNameValidator.class) String bucketName);

View File

@ -36,10 +36,9 @@ public class AWSS3ClientExpectTest extends BaseAWSS3ClientExpectTest {
HttpRequest bucketLocationRequest = HttpRequest.builder()
.method("GET")
.endpoint("https://test.s3.amazonaws.com/?location")
.addHeader("Host", "test.s3.amazonaws.com")
.endpoint("https://s3.amazonaws.com/test?location")
.addHeader("Date", CONSTANT_DATE)
.addHeader("Authorization", "AWS identity:D1rymKrEdvzvhmZXeg+Z0R+tiug=").build();
.addHeader("Authorization", "AWS identity:sOZnJSLuwnMVn7CiEKcVmpFI0rU=").build();
HttpResponse bucketLocationResponse = HttpResponse.builder()
.statusCode(200)

View File

@ -80,8 +80,7 @@ public class AWSS3ClientTest extends S3ClientTest<AWSS3Client> {
Invokable<?, ?> method = method(AWSS3Client.class, "getBucketLocation", String.class);
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("bucket-eu-west-1"));
assertRequestLineEquals(request, "GET https://bucket-eu-west-1.s3.amazonaws.com/?location HTTP/1.1");
assertNonPayloadHeadersEqual(request, "Host: bucket-eu-west-1.s3.amazonaws.com\n");
assertRequestLineEquals(request, "GET https://s3.amazonaws.com/bucket-eu-west-1?location HTTP/1.1");
assertPayloadEquals(request, null, null, false);
assertResponseParserClassEquals(method, request, ParseSax.class);
@ -116,16 +115,15 @@ public class AWSS3ClientTest extends S3ClientTest<AWSS3Client> {
Invokable<?, ?> method = method(AWSS3Client.class, "getBucketLocation", String.class);
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("bucket"));
assertRequestLineEquals(request, "GET https://bucket.s3.amazonaws.com/?location HTTP/1.1");
assertNonPayloadHeadersEqual(request, "Host: bucket.s3.amazonaws.com\n");
assertRequestLineEquals(request, "GET https://s3.amazonaws.com/bucket?location HTTP/1.1");
assertPayloadEquals(request, null, null, false);
request = (GeneratedHttpRequest) filter.filter(request);
assertRequestLineEquals(request, "GET https://bucket.s3.amazonaws.com/?location HTTP/1.1");
assertRequestLineEquals(request, "GET https://s3.amazonaws.com/bucket?location HTTP/1.1");
assertNonPayloadHeadersEqual(
request,
"Authorization: AWS identity:2fFTeYJTDwiJmaAkKj732RjNbOg=\nDate: 2009-11-08T15:54:08.897Z\nHost: bucket.s3.amazonaws.com\n");
"Authorization: AWS identity:f1Pt8/8Yr/HZahuc6KPI1B2+Mw4=\nDate: 2009-11-08T15:54:08.897Z\n");
assertPayloadEquals(request, null, null, false);
assertResponseParserClassEquals(method, request, ParseSax.class);