Aws-sdk-java-v2: Support 1.11.x's S3.getUrl and getResourceUrl

Created on 20 Nov 2018  路  6Comments  路  Source: aws/aws-sdk-java-v2

1.11.x had an operation for turning a bucket and object name into a URL. Equivalent functionality should be supported in 2.x.

feature-request

Most helpful comment

It's probably better to use 1.11.x for this feature, but here's a really gross, fragile way to do it in 2.x.

URI s3Endpoint = URI.create("https://" + S3Client.serviceMetadata().endpointFor(Region.US_WEST_2));
SdkClientConfiguration sdkClientConfiguration = SdkClientConfiguration.builder()
                                                                      .option(SdkClientOption.ENDPOINT, s3Endpoint)
                                                                      .build();
AwsS3ProtocolFactory protocolFactory = AwsS3ProtocolFactory.builder()
                                                           .clientConfiguration(sdkClientConfiguration)
                                                           .build();

GetObjectRequestMarshaller requestMarshaller = new GetObjectRequestMarshaller(protocolFactory);

GetObjectRequest getRequest = GetObjectRequest.builder().bucket("foo").key("bar").build();
SdkHttpFullRequest httpRequest = requestMarshaller.marshall(getRequest);

URI objectUri = httpRequest.getUri();

It uses internal APIs, so it's subject to break in future SDK versions, and it only uses path-style addressing. It might even be easier to just build the URL manually than use this code...

All 6 comments

It's probably better to use 1.11.x for this feature, but here's a really gross, fragile way to do it in 2.x.

URI s3Endpoint = URI.create("https://" + S3Client.serviceMetadata().endpointFor(Region.US_WEST_2));
SdkClientConfiguration sdkClientConfiguration = SdkClientConfiguration.builder()
                                                                      .option(SdkClientOption.ENDPOINT, s3Endpoint)
                                                                      .build();
AwsS3ProtocolFactory protocolFactory = AwsS3ProtocolFactory.builder()
                                                           .clientConfiguration(sdkClientConfiguration)
                                                           .build();

GetObjectRequestMarshaller requestMarshaller = new GetObjectRequestMarshaller(protocolFactory);

GetObjectRequest getRequest = GetObjectRequest.builder().bucket("foo").key("bar").build();
SdkHttpFullRequest httpRequest = requestMarshaller.marshall(getRequest);

URI objectUri = httpRequest.getUri();

It uses internal APIs, so it's subject to break in future SDK versions, and it only uses path-style addressing. It might even be easier to just build the URL manually than use this code...

Well, that's a pretty ingenious workaround!

I am new to S3 and not sure if the way I handle this is consistent.
I just added interceptor by overriding modifyHttpResponse() method by adding url header to the response header!

public class AmazonS3AssetUploadUrlInterceptor implements ExecutionInterceptor {

  @Override
  public SdkHttpResponse modifyHttpResponse(ModifyHttpResponse context, ExecutionAttributes executionAttributes) {
    return context.httpResponse().toBuilder().putHeader("url", context.httpRequest().getUri().toString()).build();
  }
}

The API is exposed through S3Utilities class.

The API can be used in 2 ways:
1) Directly construct a S3Utilities object

S3Utilities utilities = S3Utilities.builder().region(Region.US_WEST_2).build()
GetUrlRequest request = GetUrlRequest.builder().bucket("foo-bucket").key("key-without-spaces").build()
URL url = pathStyleUtilities.getUrl(request);

2) Use the utilities() method in low-level client (S3Client or S3AsyncClient). This is recommended as SDK will use the same configuration from the low-level client to create the S3Utilities object.

S3Client s3client = S3Client.create();
S3Utilities utilities = s3client.utilities();
GetUrlRequest.builder()
                            .bucket("foo-bucket")
                            .key("key-without-spaces")
                            // Use a different region other than configured on the S3Client/S3Utilities
                            .region(Region.AP_NORTHEAST_1)
                            .build();
URL url = pathStyleUtilities.getUrl(request);

How to let gradle to use the newest version?
I have implementation "software.amazon.awssdk:s3:2.5.11"
but I cannot find S3Utilities class.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

millems picture millems  路  3Comments

mscharp picture mscharp  路  5Comments

tigertoes picture tigertoes  路  6Comments

jhovell picture jhovell  路  4Comments

vhiairrassary picture vhiairrassary  路  3Comments