Skip to content

Commit 04e4e43

Browse files
committed
Add S3 custom 503 throttling detection
1 parent d97564a commit 04e4e43

File tree

2 files changed

+71
-0
lines changed

2 files changed

+71
-0
lines changed

services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/handlers/ExceptionTranslationInterceptor.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,14 @@ public Throwable modifyException(Context.FailedExecution context, ExecutionAttri
7575
.message(message)
7676
.build();
7777
}
78+
} else if (exception.statusCode() == 503 && "Slow Down".equals(errorDetails.sdkHttpResponse().statusText().orElse(null))) {
79+
return S3Exception.builder()
80+
.awsErrorDetails(fillErrorDetails(errorDetails, "SlowDown", "Please reduce your request rate."))
81+
.statusCode(503)
82+
.requestId(requestId)
83+
.extendedRequestId(extendedRequestId)
84+
.message(message)
85+
.build();
7886
} else if (errorDetails.errorMessage() == null) {
7987
// Populate the error message using the HTTP response status text. Usually that's just the value from the
8088
// HTTP spec (e.g. "Forbidden"), but sometimes S3 throws some more useful things in there, like "Slow Down".

services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/handlers/ExceptionTranslationInterceptorTest.java

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,46 @@ public void otherRequest_shouldNotThrowException() {
9898
assertThat(interceptor.modifyException(failedExecution, new ExecutionAttributes())).isEqualTo(s3Exception);
9999
}
100100

101+
@Test
102+
public void headObject503SlowDown_shouldBeThrottlingException() {
103+
S3Exception s3Exception = create503ThrottlingException();
104+
Context.FailedExecution failedExecution = getFailedExecution(s3Exception,
105+
HeadObjectRequest.builder().build());
106+
S3Exception modifiedException = (S3Exception) interceptor.modifyException(failedExecution, new ExecutionAttributes());
107+
assertThat(modifiedException.awsErrorDetails().errorCode()).isEqualTo("SlowDown");
108+
assertThat(modifiedException.isThrottlingException()).isTrue();
109+
}
110+
111+
@Test
112+
public void headBucket503SlowDown_shouldBeThrottlingException() {
113+
S3Exception s3Exception = create503ThrottlingException();
114+
Context.FailedExecution failedExecution = getFailedExecution(s3Exception,
115+
HeadBucketRequest.builder().build());
116+
S3Exception modifiedException = (S3Exception) interceptor.modifyException(failedExecution, new ExecutionAttributes());
117+
assertThat(modifiedException.awsErrorDetails().errorCode()).isEqualTo("SlowDown");
118+
assertThat(modifiedException.isThrottlingException()).isTrue();
119+
}
120+
121+
@Test
122+
public void headBucket503ServiceUnavailable_shouldNotBeThrottlingException() {
123+
S3Exception s3Exception = create503NonThrottlingException();
124+
Context.FailedExecution failedExecution = getFailedExecution(s3Exception,
125+
HeadBucketRequest.builder().build());
126+
S3Exception modifiedException = (S3Exception) interceptor.modifyException(failedExecution, new ExecutionAttributes());
127+
assertThat(modifiedException.awsErrorDetails().errorCode()).isNull();
128+
assertThat(modifiedException.isThrottlingException()).isFalse();
129+
}
130+
131+
@Test
132+
public void headObject503ServiceUnavailable_shouldNotBeThrottlingException() {
133+
S3Exception s3Exception = create503NonThrottlingException();
134+
Context.FailedExecution failedExecution = getFailedExecution(s3Exception,
135+
HeadObjectRequest.builder().build());
136+
S3Exception modifiedException = (S3Exception) interceptor.modifyException(failedExecution, new ExecutionAttributes());
137+
assertThat(modifiedException.awsErrorDetails().errorCode()).isNull();
138+
assertThat(modifiedException.isThrottlingException()).isFalse();
139+
}
140+
101141
private S3Exception create404S3Exception() {
102142
return (S3Exception) S3Exception.builder()
103143
.awsErrorDetails(AwsErrorDetails.builder()
@@ -118,4 +158,27 @@ private S3Exception create403S3Exception() {
118158
.statusCode(403)
119159
.build();
120160
}
161+
162+
private S3Exception create503ThrottlingException() {
163+
return (S3Exception) S3Exception.builder()
164+
.awsErrorDetails(AwsErrorDetails.builder()
165+
.sdkHttpResponse(SdkHttpFullResponse.builder()
166+
.statusText(
167+
"Slow Down")
168+
.build())
169+
.build())
170+
.statusCode(503)
171+
.build();
172+
}
173+
174+
private S3Exception create503NonThrottlingException() {
175+
return (S3Exception) S3Exception.builder()
176+
.awsErrorDetails(AwsErrorDetails.builder()
177+
.sdkHttpResponse(SdkHttpFullResponse.builder()
178+
.statusText("Service Unavailable")
179+
.build())
180+
.build())
181+
.statusCode(503)
182+
.build();
183+
}
121184
}

0 commit comments

Comments
 (0)