diff --git a/server/skillhub-storage/src/main/java/com/iflytek/skillhub/storage/S3StorageService.java b/server/skillhub-storage/src/main/java/com/iflytek/skillhub/storage/S3StorageService.java index 50062e85..a0efbbd0 100644 --- a/server/skillhub-storage/src/main/java/com/iflytek/skillhub/storage/S3StorageService.java +++ b/server/skillhub-storage/src/main/java/com/iflytek/skillhub/storage/S3StorageService.java @@ -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() { diff --git a/server/skillhub-storage/src/test/java/com/iflytek/skillhub/storage/S3StorageServiceTest.java b/server/skillhub-storage/src/test/java/com/iflytek/skillhub/storage/S3StorageServiceTest.java new file mode 100644 index 00000000..8ca8cae7 --- /dev/null +++ b/server/skillhub-storage/src/test/java/com/iflytek/skillhub/storage/S3StorageServiceTest.java @@ -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; + } +}