fix(storage): honor forcePathStyle for s3 presigner

This commit is contained in:
dongmucat 2026-04-07 18:29:09 +08:00
parent c2981836bb
commit 445f757535
2 changed files with 67 additions and 3 deletions

View file

@ -11,6 +11,7 @@ import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.http.apache.ApacheHttpClient;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.S3Configuration;
import software.amazon.awssdk.services.s3.model.*;
import software.amazon.awssdk.services.s3.presigner.S3Presigner;
import software.amazon.awssdk.services.s3.presigner.model.GetObjectPresignRequest;
@ -54,17 +55,24 @@ public class S3StorageService implements ObjectStorageService {
builder.endpointOverride(URI.create(properties.getEndpoint()));
}
this.s3Client = builder.build();
this.s3Presigner = buildPresigner();
ensureBucketExists();
}
S3Presigner buildPresigner() {
var presignerBuilder = S3Presigner.builder()
.region(Region.of(properties.getRegion()))
.credentialsProvider(StaticCredentialsProvider.create(
AwsBasicCredentials.create(properties.getAccessKey(), properties.getSecretKey())));
AwsBasicCredentials.create(properties.getAccessKey(), properties.getSecretKey())))
.serviceConfiguration(S3Configuration.builder()
.pathStyleAccessEnabled(properties.isForcePathStyle())
.build());
if (properties.getPublicEndpoint() != null && !properties.getPublicEndpoint().isBlank()) {
presignerBuilder.endpointOverride(URI.create(properties.getPublicEndpoint()));
} else if (properties.getEndpoint() != null && !properties.getEndpoint().isBlank()) {
presignerBuilder.endpointOverride(URI.create(properties.getEndpoint()));
}
this.s3Presigner = presignerBuilder.build();
ensureBucketExists();
return presignerBuilder.build();
}
private void ensureBucketExists() {

View file

@ -0,0 +1,56 @@
package com.iflytek.skillhub.storage;
import org.junit.jupiter.api.Test;
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
import software.amazon.awssdk.services.s3.presigner.model.GetObjectPresignRequest;
import java.net.URI;
import java.time.Duration;
import static org.assertj.core.api.Assertions.assertThat;
class S3StorageServiceTest {
@Test
void shouldUsePathStylePresignedUrlWhenForcePathStyleEnabled() {
URI presignedUrl = presignGetObjectUrl(true);
assertThat(presignedUrl.getHost()).isEqualTo("s3.us-east-1.amazonaws.com");
assertThat(presignedUrl.getPath()).isEqualTo("/test-bucket/artifacts/package.tgz");
}
@Test
void shouldUseHostStylePresignedUrlWhenForcePathStyleDisabled() {
URI presignedUrl = presignGetObjectUrl(false);
assertThat(presignedUrl.getHost()).isEqualTo("test-bucket.s3.us-east-1.amazonaws.com");
assertThat(presignedUrl.getPath()).isEqualTo("/artifacts/package.tgz");
}
private URI presignGetObjectUrl(boolean forcePathStyle) {
S3StorageService storageService = new S3StorageService(createProperties(forcePathStyle));
try (var presigner = storageService.buildPresigner()) {
var request = presigner.presignGetObject(
GetObjectPresignRequest.builder()
.signatureDuration(Duration.ofMinutes(10))
.getObjectRequest(GetObjectRequest.builder()
.bucket("test-bucket")
.key("artifacts/package.tgz")
.build())
.build()
);
return URI.create(request.url().toString());
}
}
private S3StorageProperties createProperties(boolean forcePathStyle) {
S3StorageProperties properties = new S3StorageProperties();
properties.setRegion("us-east-1");
properties.setBucket("test-bucket");
properties.setAccessKey("test-access-key");
properties.setSecretKey("test-secret-key");
properties.setEndpoint("https://s3.us-east-1.amazonaws.com");
properties.setForcePathStyle(forcePathStyle);
return properties;
}
}