My bucket has a folder “items/” where all my images go to. However, despite me accurately representing this in the key I am getting an error with the url generated when sending a post request to that url. The error mentions “The request signature we calculated does not match the signature you provided. Check your key and signing method.”
@Configuration
public class S3Config {
@Value("${aws.region}")
private String awsRegion;
@Bean
public S3Client s3Client() {
S3Client client = S3Client.builder()
.region(Region.of(awsRegion))
.build();
return client;
}
@Bean
public S3Presigner s3Presigner() {
return S3Presigner.builder()
.region(Region.of(awsRegion))
.credentialsProvider(DefaultCredentialsProvider.create())
.build();
}
}
@RestController
@RequestMapping("/s3")
public class S3Controller {
private final S3Service s3Service;
@Autowired
public S3Controller(S3Service s3Service) {
this.s3Service = s3Service;
}
// Endpoint to generate a presigned URL for PUT operations
@GetMapping("/presign-put/{filename}")
public ResponseEntity<String> getPresignedPutUrl(@PathVariable String filename) {
try {
String presignedUrl = s3Service.generatePresignedUrl(filename);
return ResponseEntity.ok(presignedUrl);
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Failed to generate presigned URL: " + e.getMessage());
}
}
}
@Service
public class S3Service {
private final S3Client s3;
private final S3Presigner presigner;
@Value("${aws.s3.bucketName}") //defined inside of application properties
private String bucketName;
public S3Service(S3Client s3, S3Presigner s3Presigner) {
this.s3 = s3;
this.presigner = s3Presigner;
}
public String generatePresignedUrl(String filename) {
String key = "items/" + filename;
PutObjectRequest putObjectRequest = PutObjectRequest.builder()
.bucket(bucketName)
.key(key)
.build();
PutObjectPresignRequest presignRequest = PutObjectPresignRequest.builder()
.putObjectRequest(putObjectRequest)
.signatureDuration(Duration.ofHours(24))
.build();
PresignedPutObjectRequest presignedRequest = presigner.presignPutObject(presignRequest);
return presignedRequest.url().toString();
}