1
15
16 package software.amazon.awssdk.services.s3.internal.handlers;
17
18 import java.util.Optional;
19 import software.amazon.awssdk.annotations.SdkInternalApi;
20 import software.amazon.awssdk.awscore.exception.AwsErrorDetails;
21 import software.amazon.awssdk.core.SdkRequest;
22 import software.amazon.awssdk.core.interceptor.Context;
23 import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
24 import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
25 import software.amazon.awssdk.services.s3.model.HeadBucketRequest;
26 import software.amazon.awssdk.services.s3.model.HeadObjectRequest;
27 import software.amazon.awssdk.services.s3.model.NoSuchBucketException;
28 import software.amazon.awssdk.services.s3.model.NoSuchKeyException;
29 import software.amazon.awssdk.services.s3.model.S3Exception;
30
31
34 @SdkInternalApi
35 public final class ExceptionTranslationInterceptor implements ExecutionInterceptor {
36
37 @Override
38 public Throwable modifyException(Context.FailedExecution context, ExecutionAttributes executionAttributes) {
39
40 if (!isS3Exception404(context.exception()) || !isHeadRequest(context.request())) {
41 return context.exception();
42 }
43
44 String message = context.exception().getMessage();
45 S3Exception exception = (S3Exception) (context.exception());
46
47 String requestIdFromHeader = exception.awsErrorDetails()
48 .sdkHttpResponse()
49 .firstMatchingHeader("x-amz-request-id")
50 .orElse(null);
51
52 String requestId = Optional.ofNullable(exception.requestId()).orElse(requestIdFromHeader);
53
54 AwsErrorDetails errorDetails = exception.awsErrorDetails();
55
56 if (context.request() instanceof HeadObjectRequest) {
57 return NoSuchKeyException.builder()
58 .awsErrorDetails(fillErrorDetails(errorDetails, "NoSuchKey",
59 "The specified key does not exist."))
60 .statusCode(404)
61 .requestId(requestId)
62 .message(message)
63 .build();
64 }
65
66 if (context.request() instanceof HeadBucketRequest) {
67 return NoSuchBucketException.builder()
68 .awsErrorDetails(fillErrorDetails(errorDetails, "NoSuchBucket",
69 "The specified bucket does not exist."))
70 .statusCode(404)
71 .requestId(requestId)
72 .message(message)
73 .build();
74 }
75
76 return context.exception();
77 }
78
79 private AwsErrorDetails fillErrorDetails(AwsErrorDetails original, String errorCode, String errorMessage) {
80 return original.toBuilder().errorMessage(errorMessage).errorCode(errorCode).build();
81 }
82
83 private boolean isHeadRequest(SdkRequest request) {
84 return (request instanceof HeadObjectRequest || request instanceof HeadBucketRequest);
85 }
86
87 private boolean isS3Exception404(Throwable thrown) {
88 if (!(thrown instanceof S3Exception)) {
89 return false;
90 }
91
92 return ((S3Exception) thrown).statusCode() == 404;
93 }
94 }
95