Skip to content

Commit 473c83c

Browse files
authored
feat: handle S3 error responses with HTTP 200 status code (smithy-lang#1117)
1 parent a7091bc commit 473c83c

File tree

2 files changed

+54
-0
lines changed

2 files changed

+54
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
package aws.sdk.kotlin.codegen.customization.s3
6+
7+
import software.amazon.smithy.kotlin.codegen.KotlinSettings
8+
import software.amazon.smithy.kotlin.codegen.core.KotlinWriter
9+
import software.amazon.smithy.kotlin.codegen.integration.KotlinIntegration
10+
import software.amazon.smithy.kotlin.codegen.model.buildSymbol
11+
import software.amazon.smithy.kotlin.codegen.model.expectShape
12+
import software.amazon.smithy.kotlin.codegen.model.isStreaming
13+
import software.amazon.smithy.kotlin.codegen.rendering.protocol.ProtocolGenerator
14+
import software.amazon.smithy.kotlin.codegen.rendering.protocol.ProtocolMiddleware
15+
import software.amazon.smithy.model.Model
16+
import software.amazon.smithy.model.shapes.OperationShape
17+
import software.amazon.smithy.model.shapes.ServiceShape
18+
19+
/**
20+
* Register interceptor to handle S3 error responses returned with an HTTP 200 status code.
21+
* see [aws-sdk-kotlin#199](https://github.com/awslabs/aws-sdk-kotlin/issues/199)
22+
*/
23+
class S3ErrorWith200StatusIntegration : KotlinIntegration {
24+
override fun enabledForService(model: Model, settings: KotlinSettings): Boolean =
25+
model.expectShape<ServiceShape>(settings.service).isS3
26+
27+
override fun customizeMiddleware(
28+
ctx: ProtocolGenerator.GenerationContext,
29+
resolved: List<ProtocolMiddleware>,
30+
): List<ProtocolMiddleware> = resolved + listOf(S3HandleError200ResponseMiddleware)
31+
}
32+
33+
private object S3HandleError200ResponseMiddleware : ProtocolMiddleware {
34+
override fun isEnabledFor(ctx: ProtocolGenerator.GenerationContext, op: OperationShape): Boolean {
35+
// we don't know for sure what operations S3 does this on. Go customized this for only a select few
36+
// like CopyObject/UploadPartCopy/CompleteMultipartUpload but Rust hit it on additional operations
37+
// (DeleteObjects).
38+
// Instead of playing whack-a-mole broadly apply this interceptor to everything but streaming responses
39+
// which adds a small amount of overhead to response processing.
40+
val output = ctx.model.expectShape(op.output.get())
41+
return output.members().none { it.isStreaming || ctx.model.expectShape(it.target).isStreaming }
42+
}
43+
44+
override val name: String = "Handle200ErrorsInterceptor"
45+
override fun render(ctx: ProtocolGenerator.GenerationContext, op: OperationShape, writer: KotlinWriter) {
46+
val symbol = buildSymbol {
47+
name = this@S3HandleError200ResponseMiddleware.name
48+
namespace = ctx.settings.pkg.subpackage("internal")
49+
}
50+
51+
writer.write("op.interceptors.add(#T)", symbol)
52+
}
53+
}

codegen/smithy-aws-kotlin-codegen/src/main/resources/META-INF/services/software.amazon.smithy.kotlin.codegen.integration.KotlinIntegration

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ aws.sdk.kotlin.codegen.customization.s3.HostPrefixRequestRouteFilter
2323
aws.sdk.kotlin.codegen.customization.s3.UnwrappedXmlOutputIntegration
2424
aws.sdk.kotlin.codegen.customization.s3control.HostPrefixFilter
2525
aws.sdk.kotlin.codegen.customization.s3control.ClientConfigIntegration
26+
aws.sdk.kotlin.codegen.customization.s3.S3ErrorWith200StatusIntegration
2627
aws.sdk.kotlin.codegen.customization.apigateway.ApiGatewayAddAcceptHeader
2728
aws.sdk.kotlin.codegen.customization.glacier.GlacierAddVersionHeader
2829
aws.sdk.kotlin.codegen.customization.glacier.GlacierAccountIdDefault

0 commit comments

Comments
 (0)