@@ -22,15 +22,15 @@ import software.amazon.smithy.model.shapes.OperationShape
2222import software.amazon.smithy.model.shapes.StructureShape
2323
2424/* *
25- * Adds a middleware that enables sending flexible checksums during an HTTP request
25+ * Handles flexible checksum requests
2626 */
2727class FlexibleChecksumsRequest : KotlinIntegration {
28- override fun enabledForService (model : Model , settings : KotlinSettings ) = model
29- .shapes<OperationShape >()
30- .any { it.hasTrait<HttpChecksumTrait >() }
28+ override fun enabledForService (model : Model , settings : KotlinSettings ) =
29+ model.isTraitApplied(HttpChecksumTrait ::class .java)
3130
3231 override fun additionalServiceConfigProps (ctx : CodegenContext ): List <ConfigProperty > =
3332 listOf (
33+ // Allows flexible checksum request configuration
3434 ConfigProperty {
3535 name = " requestChecksumCalculation"
3636 symbol = RuntimeTypes .SmithyClient .Config .HttpChecksumConfigOption
@@ -42,66 +42,96 @@ class FlexibleChecksumsRequest : KotlinIntegration {
4242 )
4343
4444 override fun customizeMiddleware (ctx : ProtocolGenerator .GenerationContext , resolved : List <ProtocolMiddleware >) =
45- resolved + flexibleChecksumsRequestMiddleware + configBusinessMetrics
46-
47- private val configBusinessMetrics = object : ProtocolMiddleware {
48- override val name: String = " requestChecksumCalculationBusinessMetric"
49-
50- override fun isEnabledFor (ctx : ProtocolGenerator .GenerationContext , op : OperationShape ): Boolean =
51- op.hasTrait<HttpChecksumTrait >()
52-
53- override fun render (ctx : ProtocolGenerator .GenerationContext , op : OperationShape , writer : KotlinWriter ) {
54- writer.withBlock(" when(config.requestChecksumCalculation) {" , " }" ) {
55- writer.write(
56- " #T.WHEN_SUPPORTED -> op.context.#T(#T.FLEXIBLE_CHECKSUMS_REQ_WHEN_SUPPORTED)" ,
57- RuntimeTypes .SmithyClient .Config .HttpChecksumConfigOption ,
58- RuntimeTypes .Core .BusinessMetrics .emitBusinessMetric,
59- RuntimeTypes .Core .BusinessMetrics .SmithyBusinessMetric ,
60- )
61- writer.write(
62- " #T.WHEN_REQUIRED -> op.context.#T(#T.FLEXIBLE_CHECKSUMS_REQ_WHEN_REQUIRED)" ,
63- RuntimeTypes .SmithyClient .Config .HttpChecksumConfigOption ,
64- RuntimeTypes .Core .BusinessMetrics .emitBusinessMetric,
65- RuntimeTypes .Core .BusinessMetrics .SmithyBusinessMetric ,
66- )
67- }
68- }
69- }
45+ resolved + requestChecksumCalculationBusinessMetric + httpChecksumDefaultAlgorithmMiddleware + flexibleChecksumsRequestMiddleware
46+ }
7047
71- private val flexibleChecksumsRequestMiddleware = object : ProtocolMiddleware {
72- override val name: String = " flexibleChecksumsRequestMiddleware"
48+ /* *
49+ * Emits business metric based on `requestChecksumCalculation` client config
50+ */
51+ private val requestChecksumCalculationBusinessMetric = object : ProtocolMiddleware {
52+ override val name: String = " requestChecksumCalculationBusinessMetric"
7353
74- override fun isEnabledFor (ctx : ProtocolGenerator .GenerationContext , op : OperationShape ): Boolean {
75- val httpChecksumTrait = op.getTrait<HttpChecksumTrait >()
76- val input = op.input.getOrNull()?.let { ctx.model.expectShape<StructureShape >(it) }
54+ override fun isEnabledFor (ctx : ProtocolGenerator .GenerationContext , op : OperationShape ): Boolean =
55+ op.hasTrait<HttpChecksumTrait >()
7756
78- return (httpChecksumTrait != null ) &&
79- (httpChecksumTrait.requestAlgorithmMember?.getOrNull() != null ) &&
80- (input?.memberNames?.any { it == httpChecksumTrait.requestAlgorithmMember.get() } == true )
57+ override fun render (ctx : ProtocolGenerator .GenerationContext , op : OperationShape , writer : KotlinWriter ) {
58+ writer.withBlock(" when(config.requestChecksumCalculation) {" , " }" ) {
59+ // Supported
60+ writer.write(
61+ " #T.WHEN_SUPPORTED -> op.context.#T(#T.FLEXIBLE_CHECKSUMS_REQ_WHEN_SUPPORTED)" ,
62+ RuntimeTypes .SmithyClient .Config .HttpChecksumConfigOption ,
63+ RuntimeTypes .Core .BusinessMetrics .emitBusinessMetric,
64+ RuntimeTypes .Core .BusinessMetrics .SmithyBusinessMetric ,
65+ )
66+ // Required
67+ writer.write(
68+ " #T.WHEN_REQUIRED -> op.context.#T(#T.FLEXIBLE_CHECKSUMS_REQ_WHEN_REQUIRED)" ,
69+ RuntimeTypes .SmithyClient .Config .HttpChecksumConfigOption ,
70+ RuntimeTypes .Core .BusinessMetrics .emitBusinessMetric,
71+ RuntimeTypes .Core .BusinessMetrics .SmithyBusinessMetric ,
72+ )
8173 }
74+ }
75+ }
8276
83- override fun render (ctx : ProtocolGenerator .GenerationContext , op : OperationShape , writer : KotlinWriter ) {
84- val inputSymbol = ctx.symbolProvider.toSymbol(ctx.model.expectShape(op.inputShape))
77+ /* *
78+ * Adds default checksum algorithm to the execution context
79+ */
80+ private val httpChecksumDefaultAlgorithmMiddleware = object : ProtocolMiddleware {
81+ override val name: String = " httpChecksumDefaultAlgorithmMiddleware"
82+ override val order: Byte = - 2 // Before S3 Express (possibly) changes the default (-1) and before calculating checksum (0)
8583
86- val httpChecksumTrait = op.getTrait<HttpChecksumTrait >()!!
84+ override fun isEnabledFor (ctx : ProtocolGenerator .GenerationContext , op : OperationShape ): Boolean =
85+ requestChecksumsConfigured(ctx, op)
8786
88- val requestAlgorithmMember = ctx.model.expectShape<StructureShape >(op.input.get())
89- .members()
90- .first { it.memberName == httpChecksumTrait.requestAlgorithmMember.get() }
87+ override fun render (ctx : ProtocolGenerator .GenerationContext , op : OperationShape , writer : KotlinWriter ) {
88+ writer.write(
89+ " op.context[#T.DefaultChecksumAlgorithm] = #S" ,
90+ RuntimeTypes .HttpClient .Operation .HttpOperationContext ,
91+ " CRC32" ,
92+ )
93+ }
94+ }
95+
96+ /* *
97+ * Adds interceptor to handle flexible checksum request calculation
98+ */
99+ private val flexibleChecksumsRequestMiddleware = object : ProtocolMiddleware {
100+ override val name: String = " flexibleChecksumsRequestMiddleware"
101+
102+ override fun isEnabledFor (ctx : ProtocolGenerator .GenerationContext , op : OperationShape ): Boolean =
103+ requestChecksumsConfigured(ctx, op)
91104
92- val requestAlgorithmMemberName = ctx.symbolProvider.toMemberName(requestAlgorithmMember)
93- val requestChecksumRequired = httpChecksumTrait.isRequestChecksumRequired
105+ override fun render (ctx : ProtocolGenerator .GenerationContext , op : OperationShape , writer : KotlinWriter ) {
106+ val httpChecksumTrait = op.getTrait<HttpChecksumTrait >()!!
107+ val requestChecksumRequired = httpChecksumTrait.isRequestChecksumRequired
108+ val requestAlgorithmMember = ctx.model.expectShape<StructureShape >(op.input.get())
109+ .members()
110+ .first { it.memberName == httpChecksumTrait.requestAlgorithmMember.get() }
111+ val requestAlgorithmMemberName = ctx.symbolProvider.toMemberName(requestAlgorithmMember)
94112
95- writer.withBlock(
96- " op.interceptors.add(#T<#T>(" ,
97- " ))" ,
98- RuntimeTypes .HttpClient .Interceptors .FlexibleChecksumsRequestInterceptor ,
99- inputSymbol,
100- ) {
101- writer.write(" #L," , requestChecksumRequired)
102- writer.write(" config.requestChecksumCalculation," )
103- writer.write(" input.#L?.value," , requestAlgorithmMemberName)
104- }
113+ writer.withBlock(
114+ " op.interceptors.add(#T(" ,
115+ " ))" ,
116+ RuntimeTypes .HttpClient .Interceptors .FlexibleChecksumsRequestInterceptor ,
117+ ) {
118+ writer.write(" #L," , requestChecksumRequired)
119+ writer.write(" config.requestChecksumCalculation," )
120+ writer.write(" input.#L?.value," , requestAlgorithmMemberName)
105121 }
106122 }
107123}
124+
125+ /* *
126+ * Determines if an operation is set up to send flexible request checksums
127+ */
128+ private fun requestChecksumsConfigured (ctx : ProtocolGenerator .GenerationContext , op : OperationShape ): Boolean {
129+ val httpChecksumTrait = op.getTrait<HttpChecksumTrait >()
130+ val inputShape = op.input.getOrNull()?.let { ctx.model.expectShape<StructureShape >(it) }
131+
132+ return (
133+ (httpChecksumTrait != null ) &&
134+ (httpChecksumTrait.requestAlgorithmMember?.getOrNull() != null ) &&
135+ (inputShape?.memberNames?.any { it == httpChecksumTrait.requestAlgorithmMember.get() } == true )
136+ )
137+ }
0 commit comments