@@ -56,9 +56,8 @@ data class PresignableOperation(
5656 * This integration applies to any AWS service that provides presign capability on one or more operations.
5757 */
5858class PresignerGenerator : KotlinIntegration {
59-
6059 /* *
61- * Identifies the [PresignConfigFn ] section for overriding generated implementation.
60+ * Identifies the [PresignConfigFnSection ] section for overriding generated implementation.
6261 */
6362 object PresignConfigFnSection : SectionId {
6463 const val CodegenContext = " CodegenContext"
@@ -183,67 +182,25 @@ class PresignerGenerator : KotlinIntegration {
183182 }
184183
185184 // Generate presign config builder
185+ val clientProperties: List <ClientConfigProperty > = getClientProperties(sigv4ServiceName, serviceShape.sdkId)
186186 val rc = RenderingContext (writer, serviceShape, ctx.model, ctx.symbolProvider, ctx.settings)
187- renderPresignConfigBuilder(writer, presignConfigTypeName, sigv4ServiceName, serviceShape.sdkId, rc )
187+ renderPresignConfigBuilder(writer, presignConfigTypeName, rc, clientProperties )
188188 }
189189
190- private fun renderPresignConfigBuilder (writer : KotlinWriter , presignConfigTypeName : String , sigv4ServiceName : String , serviceId : String , renderingContext : RenderingContext < ServiceShape >) {
190+ private fun renderPresignConfigBuilder (writer : KotlinWriter , presignConfigTypeName : String , renderingContext : RenderingContext < ServiceShape >, clientProperties : List < ClientConfigProperty >) {
191191 writer.dokka {
192192 write(" Provides a subset of the service client configuration necessary to presign a request." )
193193 write(" This type can be used to presign requests in cases where an existing service client" )
194194 write(" instance is not available." )
195195 }
196196 writer.addImport(AwsRuntimeTypes .Core .ClientException )
197197 writer.putContext(" configClass.name" , presignConfigTypeName)
198- val credentialsProviderProperty = ClientConfigProperty {
199- symbol = AwsRuntimeTypes .Types .CredentialsProvider
200- name = " credentialsProvider"
201- documentation = " The AWS credentials provider to use for authenticating requests. If not provided a [aws.sdk.kotlin.runtime.auth.credentials.DefaultChainCredentialsProvider] instance will be used."
202- baseClass = AwsRuntimeTypes .Signing .ServicePresignConfig
203- propertyType = ClientConfigPropertyType .RequiredWithDefault (" DefaultChainCredentialsProvider()" )
204- }
205- val endpointResolverProperty = ClientConfigProperty {
206- symbol = AwsRuntimeTypes .Endpoint .AwsEndpointResolver
207- name = " endpointResolver"
208- documentation = " Determines the endpoint (hostname) to make requests to. When not provided a default resolver is configured automatically. This is an advanced client option."
209- baseClass = AwsRuntimeTypes .Signing .ServicePresignConfig
210- propertyType = ClientConfigPropertyType .RequiredWithDefault (" DefaultEndpointResolver()" )
211- }
212- val region = ClientConfigProperty {
213- symbol = buildSymbol {
214- name = " String"
215- namespace = " kotlin"
216- nullable = true
217- }
218- name = " region"
219- documentation = " AWS region to make requests for"
220- baseClass = AwsRuntimeTypes .Signing .ServicePresignConfig
221- propertyType = ClientConfigPropertyType .Required ()
222- }
223- val signingNameProperty = ClientConfigProperty {
224- symbol = KotlinTypes .String
225- name = " signingName"
226- documentation = " Service identifier used to sign requests"
227- baseClass = AwsRuntimeTypes .Signing .ServicePresignConfig
228- propertyType = ClientConfigPropertyType .ConstantValue (sigv4ServiceName.dq())
229- }
230- val serviceIdProperty = ClientConfigProperty {
231- symbol = KotlinTypes .String
232- name = " serviceId"
233- documentation = " Service identifier used to resolve endpoints"
234- baseClass = AwsRuntimeTypes .Signing .ServicePresignConfig
235- propertyType = ClientConfigPropertyType .ConstantValue (serviceId.dq())
236- }
237198
238199 val ccg = ClientConfigGenerator (
239200 renderingContext,
240201 false ,
241202 AwsRuntimeTypes .Signing .ServicePresignConfig ,
242- credentialsProviderProperty,
243- endpointResolverProperty,
244- region,
245- signingNameProperty,
246- serviceIdProperty
203+ * clientProperties.toTypedArray()
247204 )
248205 ccg.render()
249206 }
@@ -351,4 +308,85 @@ class PresignerGenerator : KotlinIntegration {
351308 write(" return createPresignedRequest(presignConfig, $requestConfigFnName (this, durationSeconds))" )
352309 }
353310 }
311+
312+ // Provide all client properties for a presigner client
313+ private fun getClientProperties (sigv4ServiceName : String , serviceId : String ): List <ClientConfigProperty > =
314+ listOf (
315+ ClientConfigProperty {
316+ symbol = AwsRuntimeTypes .Types .CredentialsProvider
317+ name = " credentialsProvider"
318+ documentation = " The AWS credentials provider to use for authenticating requests. If not provided a [aws.sdk.kotlin.runtime.auth.credentials.DefaultChainCredentialsProvider] instance will be used."
319+ baseClass = AwsRuntimeTypes .Signing .ServicePresignConfig
320+ propertyType = ClientConfigPropertyType .RequiredWithDefault (" DefaultChainCredentialsProvider()" )
321+ },
322+ ClientConfigProperty {
323+ symbol = AwsRuntimeTypes .Endpoint .AwsEndpointResolver
324+ name = " endpointResolver"
325+ documentation = " Determines the endpoint (hostname) to make requests to. When not provided a default resolver is configured automatically. This is an advanced client option."
326+ baseClass = AwsRuntimeTypes .Signing .ServicePresignConfig
327+ propertyType = ClientConfigPropertyType .RequiredWithDefault (" DefaultEndpointResolver()" )
328+ },
329+ ClientConfigProperty {
330+ symbol = buildSymbol {
331+ name = " String"
332+ namespace = " kotlin"
333+ nullable = true
334+ }
335+ name = " region"
336+ documentation = " AWS region to make requests for"
337+ baseClass = AwsRuntimeTypes .Signing .ServicePresignConfig
338+ propertyType = ClientConfigPropertyType .Required ()
339+ },
340+ ClientConfigProperty {
341+ symbol = KotlinTypes .String
342+ name = " signingName"
343+ documentation = " Service identifier used to sign requests"
344+ baseClass = AwsRuntimeTypes .Signing .ServicePresignConfig
345+ propertyType = ClientConfigPropertyType .ConstantValue (sigv4ServiceName.dq())
346+ },
347+ ClientConfigProperty {
348+ symbol = KotlinTypes .String
349+ name = " serviceId"
350+ documentation = " Service identifier used to resolve endpoints"
351+ baseClass = AwsRuntimeTypes .Signing .ServicePresignConfig
352+ propertyType = ClientConfigPropertyType .ConstantValue (serviceId.dq())
353+ },
354+ ClientConfigProperty {
355+ symbol = buildSymbol {
356+ name = " Boolean"
357+ namespace = " kotlin"
358+ nullable = true
359+ }
360+ name = " useDoubleUriEncode"
361+ documentation = " Determines if presigner should double encode Uri"
362+ baseClass = AwsRuntimeTypes .Signing .ServicePresignConfig
363+ propertyType = ClientConfigPropertyType .ConstantValue (useDoubleUriEncodeValueForService(serviceId))
364+ },
365+ ClientConfigProperty {
366+ symbol = buildSymbol {
367+ name = " Boolean"
368+ namespace = " kotlin"
369+ nullable = true
370+ }
371+ name = " normalizeUriPath"
372+ documentation = " Determines if presigned URI path will be normalized"
373+ baseClass = AwsRuntimeTypes .Signing .ServicePresignConfig
374+ propertyType = ClientConfigPropertyType .ConstantValue (normalizeUriPathValueForService(serviceId))
375+ }
376+ )
377+
378+ // Determine useDoubleUriEncode setting based on service
379+ // From https://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html:
380+ // "Each path segment must be URI-encoded twice (except for Amazon S3 which only gets URI-encoded once)."
381+ private fun useDoubleUriEncodeValueForService (serviceId : String ): String =
382+ when (serviceId) {
383+ " S3" -> false
384+ else -> true
385+ }.toString()
386+
387+ // Determine normalizeUriPath setting based on service
388+ // From https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-header-based-auth.html#canonical-request:
389+ // "You do not normalize URI paths for requests to Amazon S3. For example, you may have a bucket with an object named "my-object//example//photo.user". Normalizing the path changes the object name in the request to "my-object/example/photo.user". This is an incorrect path for that object."
390+ private fun normalizeUriPathValueForService (serviceId : String ): String =
391+ useDoubleUriEncodeValueForService(serviceId)
354392}
0 commit comments