So I have this snippet (in kotlin, but it shouldnt matter)
val s3Client : S3Client = S3Client.builder()
.endpointOverride(URI("http://localhost:12345")).region(Region.US_EAST_1)
.advancedConfiguration(S3AdvancedConfiguration.builder().pathStyleAccessEnabled(true).build())
.build()
The exception is the following
Caused by: org.apache.http.conn.HttpHostConnectException: Connect to localhost:80 [localhost/127.0.0.1] failed: Connection refused (Connection refused)
As you can see here, the port is suddenly set to 80 instead of 12345, seems to get lost when going through all the stages at some point but hadnt had time to debug further.
The following in Java works fine:
S3Client client = S3Client.builder()
.endpointOverride(new URI("http://localhost:12345"))
.region(Region.US_EAST_1)
.advancedConfiguration(S3AdvancedConfiguration.builder().pathStyleAccessEnabled(true).build())
.build();
client.listBuckets();
In that it gives the following error:
Exception in thread "main" software.amazon.awssdk.SdkClientException: Unable to execute HTTP request: Connect to localhost:12345 [localhost/127.0.0.1] failed: Connection refused (Connection refused)
Not sure why URI would act differently under kotlin. Which version of the SDK are you using?
So this also fails in java for me (created a fresh gradle project with this in a main method):
public static void main(String[] args) throws Exception {
System.setProperty("aws.accessKeyId", "foo");
System.setProperty("aws.secretAccessKey", "bar");
S3Client s3Client = S3Client.builder()
.endpointOverride(new URI("http://localhost:12345")).region(Region.US_EAST_1)
.advancedConfiguration(S3AdvancedConfiguration.builder().pathStyleAccessEnabled(true).build())
.build();
CreateBucketResponse response = s3Client.createBucket(CreateBucketRequest.builder().bucket("foo").build());
}
I am using 2.0.0-preview-2
Update: Your list buckets call actually works and goes to the correct port! Mine however fails.
I've found the issue and will try and get a fix out to master today. We don't currently have a set process for doing releases while in developer preview but as this is a bug we can cut one for this once it is fixed.
thanks, appreciate the quick response!
I was having the exact same issue when mocking AWS using a dockerized LocalStack and overriding the s3 client endpoint to localhost:4572.
Building and pointing to preview-3-SNAPSHOT on finks/handler-context fixed this problem for the sync S3 client: I can create/delete/list buckets, put/get/delete/list objects. (thank you!)
The async S3 client however is still losing the endpoint override and throwing software.amazon.awssdk.SdkClientException: Unable to execute HTTP request: Connection refused: localhost/127.0.0.1:80 when I attempt to create a new bucket. I can successfully list buckets with async client (this worked in preview-2 release as well), but attempts to create a new bucket fail.
val region = Region.US_WEST_1
val s3Configuration = S3AdvancedConfiguration.builder
.pathStyleAccessEnabled(true)
.build
val credentials = ProfileCredentialsProvider.builder
.profileName("localstack") // matches a profile in .aws/credentials file
.build
val s3Client = S3AsyncClient.builder
.endpointOverride(new URI("http://localhost:4572"))
.advancedConfiguration(s3Configuration)
.region(region)
.credentialsProvider(credentials)
.build
"AWS S3 Async Client" should {
val bucketName = "test-bucket-abc"
// this test passes in preview-3-SNAPSHOT finks/handler-context
"request s3 bucket list" in {
val response: CompletableFuture[ListBucketsResponse] = s3Client.listBuckets()
response.toScala.map({
case lbr: ListBucketsResponse => assert(true) // pass (successfully received response)
case _ => assert(false) // fail (failed to retrieve response of type ListBucketResponse)
})
}
// this test throws: software.amazon.awssdk.SdkClientException: Unable to execute HTTP request: Connection refused: localhost/127.0.0.1:80 in preview-3-SNAPSHOT finks/handler-context
"create a new bucket" in {
val bucketConfiguration = CreateBucketConfiguration.builder
.locationConstraint(region.value())
.build
val req = CreateBucketRequest.builder
.bucket("some-new-bucket")
.createBucketConfiguration(bucketConfiguration)
.build
s3Client.createBucket(req).toScala.map({
case cbr: CreateBucketResponse => assert(true) // pass (successfully received response)
case _ => assert(fail) // fail (failed to retrieve response of type CreateBucketResponse)
})
}
}
As a point of comparison, read and write operations with the async dynamo DB client are working well with endpoint override and LocalStack for both preview-2 and preview-3-SNAPSHOT/finks/handler-context.
Would the fix here be related to the fix for the synchronous client, or am I missing something? Thanks!
any update here or downloadable snapshot that I could test against? happy to help debugging
@spinscale, @tabSF, master should now have this fix in for the async and sync clients. Was fixed by PR #97
We'll try and get a release out in Maven soon.
@spfink thanks for the update -- I built preview-3 off of the current master branch, but previously functioning code is now erroring out:
val handler: StreamingResponseHandler[GetObjectResponse, Void] = StreamingResponseHandler.toFile(Paths.get("tmp/foo.json"))
on compile results in:
[error] found : software.amazon.awssdk.sync.StreamingResponseHandler[Object,Object]
[error] required: software.amazon.awssdk.sync.StreamingResponseHandler[software.amazon.awssdk.services.s3.model.GetObjectResponse,Void]
Using the .toOutputStream method with ByteArrayOutputStream throws the same error. Is this a regression, or the result of a planned API change that's not in docs yet?
@tabSF we made some changes to that interface, it was missing type params before and we changed it from returning Void to returning the GetObjectResponse object. The following code should compile.
val handler: StreamingResponseHandler[GetObjectResponse, GetObjectResponse] = StreamingResponseHandler.toFile(Paths.get("tmp/foo.json"))
Additionally there is now an overload of getObject on the S3Client interface that takes a Path so you don't have to mess around with StreamingResponseHandler.
s3Client.getObject(getObjectRequest, Paths.get("..."))
I'll make sure the docs are updated to reflect this.
@shorea those changes make a lot of sense, that code works perfectly now - thanks!
@spfink master branch for preview-3 appears to resolve the original problem of remembering custom endpoints, for both sync and async S3 clients.
I can list and create buckets with the S3 async client now, but now hitting timeouts for put object and delete bucket commands (though the delete request is succeeding). I'll experiment some more this weekend and open a new issue if I can't find a solution, perhaps I'm configuring things incorrectly or LocalStack isn't playing well.
Thanks for your help, new APIs are looking good!
@tabSF I'm having similar issue #130 . is preview-3 for java available in maven central repo?
@gpj1 I don't believe they've released preview-3 yet, I'm just cloning and building directly off of this repo's master branch:
mvn clean install -Dmaven.test.skip=true
and then importing directly into my project as 2.0.0-preview-3-SNAPSHOT (per version in pom files of the master branch) from my local maven repository
Closing this issue. This has been fixed in 2.0.0-preview-4 which is now available on Maven.