From 92b90d4a1d0943ffd1b09da6960eaa2a6592002f Mon Sep 17 00:00:00 2001 From: Ken Gilmer Date: Mon, 23 Aug 2021 14:22:44 -0700 Subject: [PATCH 1/5] WIP --- .../aws/sdk/kotlin/runtime/auth/Presigner.kt | 54 +++++++++---------- .../aws/sdk/kotlin/codegen/AwsRuntimeTypes.kt | 1 - .../sdk/kotlin/codegen/PresignerGenerator.kt | 10 ++-- .../sdk/kotlin/services/polly/PollyTest.kt | 2 +- 4 files changed, 32 insertions(+), 35 deletions(-) diff --git a/aws-runtime/auth/common/src/aws/sdk/kotlin/runtime/auth/Presigner.kt b/aws-runtime/auth/common/src/aws/sdk/kotlin/runtime/auth/Presigner.kt index ca8d555e8ea..5befeaf289c 100644 --- a/aws-runtime/auth/common/src/aws/sdk/kotlin/runtime/auth/Presigner.kt +++ b/aws-runtime/auth/common/src/aws/sdk/kotlin/runtime/auth/Presigner.kt @@ -5,7 +5,7 @@ import aws.sdk.kotlin.crt.auth.signing.AwsSignedBodyHeaderType import aws.sdk.kotlin.crt.auth.signing.AwsSignedBodyValue import aws.sdk.kotlin.crt.auth.signing.AwsSigner import aws.sdk.kotlin.crt.auth.signing.AwsSigningConfig -import aws.sdk.kotlin.crt.http.HttpRequest +import aws.sdk.kotlin.crt.http.HttpRequest as CrtHttpRequest import aws.sdk.kotlin.runtime.crt.toCrtHeaders import aws.sdk.kotlin.runtime.crt.toSdkHeaders import aws.sdk.kotlin.runtime.endpoint.EndpointResolver @@ -14,7 +14,12 @@ import aws.smithy.kotlin.runtime.http.HttpMethod import aws.smithy.kotlin.runtime.http.Protocol import aws.smithy.kotlin.runtime.http.QueryParameters import aws.smithy.kotlin.runtime.http.Url +import aws.smithy.kotlin.runtime.http.request.HttpRequest +import aws.smithy.kotlin.runtime.http.request.HttpRequestBuilder +import aws.smithy.kotlin.runtime.http.util.splitAsQueryParameters import aws.smithy.kotlin.runtime.util.InternalApi +import aws.smithy.kotlin.runtime.util.text.splitAsQueryString +import kotlin.math.sign /** * The service configuration details for a presigned request @@ -63,26 +68,14 @@ public data class PresignedRequestConfig( public val additionalHeaders: Headers = Headers.Empty ) -/** - * Properties of an HTTP request that has been presigned - * @property method HTTP method to use when initiating the request - * @property url HTTP url of the presigned request - * @property headers Headers that must be sent with the request - */ -public data class PresignedRequest( - val method: HttpMethod, - val url: String, - val headers: Headers -) - /** * Generate a presigned request given the service and operation configurations. * @param serviceConfig The service configuration to use in signing the request * @param requestConfig The presign configuration to use in signing the request - * @return a [PresignedRequest] that can be executed by any HTTP client within the specified duration. + * @return a [HttpRequest] that can be executed by any HTTP client within the specified duration. */ @InternalApi -public suspend fun createPresignedRequest(serviceConfig: ServicePresignConfig, requestConfig: PresignedRequestConfig): PresignedRequest { +public suspend fun createPresignedRequest(serviceConfig: ServicePresignConfig, requestConfig: PresignedRequestConfig): HttpRequest { val crtCredentials = serviceConfig.credentialsProvider.getCredentials().toCrt() val endpoint = serviceConfig.endpointResolver.resolve(serviceConfig.serviceId, serviceConfig.region) @@ -96,22 +89,27 @@ public suspend fun createPresignedRequest(serviceConfig: ServicePresignConfig, r expirationInSeconds = requestConfig.durationSeconds } - val url = Url(Protocol.HTTPS, endpoint.hostname, path = requestConfig.path, parameters = requestConfig.queryString) + val unsignedUrl = Url(Protocol.HTTPS, endpoint.hostname, path = requestConfig.path, parameters = requestConfig.queryString) - val headers = aws.sdk.kotlin.crt.http.Headers.build { - append("Host", endpoint.hostname) - appendAll(requestConfig.additionalHeaders.toCrtHeaders()) - } - val request = HttpRequest( + val request = CrtHttpRequest( requestConfig.method.name, - url.encodedPath, - headers + unsignedUrl.encodedPath, + aws.sdk.kotlin.crt.http.Headers.build { + append("Host", endpoint.hostname) + appendAll(requestConfig.additionalHeaders.toCrtHeaders()) + } ) val signedRequest = AwsSigner.signRequest(request, signingConfig) - return PresignedRequest( - requestConfig.method, - "${endpoint.protocol}://${endpoint.hostname}${signedRequest.encodedPath}", - signedRequest.headers.toSdkHeaders() - ) + val path = signedRequest.encodedPath.substringBefore('?') + val params = signedRequest.encodedPath.substring(path.length + 1).splitAsQueryParameters() + + return HttpRequestBuilder().apply { + this.url.host = unsignedUrl.host + this.url.path = path + this.url.parameters.appendAll(params) + this.url.scheme = unsignedUrl.scheme + this.headers.appendAll(signedRequest.headers.toSdkHeaders()) + this.method = HttpMethod.parse(signedRequest.method) + }.build() } diff --git a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/aws/sdk/kotlin/codegen/AwsRuntimeTypes.kt b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/aws/sdk/kotlin/codegen/AwsRuntimeTypes.kt index bbee4da2cf3..725e90432d3 100644 --- a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/aws/sdk/kotlin/codegen/AwsRuntimeTypes.kt +++ b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/aws/sdk/kotlin/codegen/AwsRuntimeTypes.kt @@ -43,7 +43,6 @@ object AwsRuntimeTypes { val CredentialsProvider = runtimeSymbol("CredentialsProvider", AwsKotlinDependency.AWS_AUTH) val createPresignedRequest = runtimeSymbol("createPresignedRequest", AwsKotlinDependency.AWS_AUTH) val DefaultChainCredentialsProvider = runtimeSymbol("DefaultChainCredentialsProvider", AwsKotlinDependency.AWS_AUTH) - val PresignedRequest = runtimeSymbol("PresignedRequest", AwsKotlinDependency.AWS_AUTH) val PresignedRequestConfig = runtimeSymbol("PresignedRequestConfig", AwsKotlinDependency.AWS_AUTH) val ServicePresignConfig = runtimeSymbol("ServicePresignConfig", AwsKotlinDependency.AWS_AUTH) val SigningLocation = runtimeSymbol("SigningLocation", AwsKotlinDependency.AWS_AUTH) diff --git a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/aws/sdk/kotlin/codegen/PresignerGenerator.kt b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/aws/sdk/kotlin/codegen/PresignerGenerator.kt index 11df4121dea..fd9a4a014d5 100644 --- a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/aws/sdk/kotlin/codegen/PresignerGenerator.kt +++ b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/aws/sdk/kotlin/codegen/PresignerGenerator.kt @@ -75,11 +75,11 @@ class PresignerGenerator : KotlinIntegration { // Symbols which should be imported private val presignerRuntimeSymbols = setOf( // smithy-kotlin types + RuntimeTypes.Http.Request.HttpRequest, RuntimeTypes.Core.ExecutionContext, // AWS types AwsRuntimeTypes.Auth.CredentialsProvider, AwsRuntimeTypes.Auth.DefaultChainCredentialsProvider, - AwsRuntimeTypes.Auth.PresignedRequest, AwsRuntimeTypes.Auth.PresignedRequestConfig, AwsRuntimeTypes.Auth.ServicePresignConfig, AwsRuntimeTypes.Auth.SigningLocation, @@ -327,10 +327,10 @@ class PresignerGenerator : KotlinIntegration { write("Presign a [$requestTypeName] using a [$serviceClientTypeName].") write("@param serviceClient the client providing properties used to generate the presigned request.") write("@param durationSeconds the amount of time from signing for which the request is valid, with seconds granularity.") - write("@return The [PresignedRequest] that can be invoked within the specified time window.") + write("@return The [HttpRequest] that can be invoked within the specified time window.") } // FIXME ~ Replace or add additional function, swap ULong type for kotlin.time.Duration when type becomes stable - writer.withBlock("suspend fun $requestTypeName.presign(serviceClient: $serviceClientTypeName, durationSeconds: ULong): PresignedRequest {", "}\n") { + writer.withBlock("suspend fun $requestTypeName.presign(serviceClient: $serviceClientTypeName, durationSeconds: ULong): HttpRequest {", "}\n") { withBlock("val serviceClientConfig = $presignConfigTypeName {", "}") { write("credentialsProvider = serviceClient.config.credentialsProvider ?: DefaultChainCredentialsProvider()") write("endpointResolver = serviceClient.config.endpointResolver ?: DefaultEndpointResolver()") @@ -345,10 +345,10 @@ class PresignerGenerator : KotlinIntegration { write("Presign a [$requestTypeName] using a [ServicePresignConfig].") write("@param serviceClientConfig the client configuration used to generate the presigned request") write("@param durationSeconds the amount of time from signing for which the request is valid, with seconds granularity.") - write("@return The [PresignedRequest] that can be invoked within the specified time window.") + write("@return The [HttpRequest] that can be invoked within the specified time window.") } // FIXME ~ Replace or add additional function, swap ULong type for kotlin.time.Duration when type becomes stable - writer.withBlock("suspend fun $requestTypeName.presign(serviceClientConfig: ServicePresignConfig, durationSeconds: ULong): PresignedRequest {", "}\n") { + writer.withBlock("suspend fun $requestTypeName.presign(serviceClientConfig: ServicePresignConfig, durationSeconds: ULong): HttpRequest {", "}\n") { write("return createPresignedRequest(serviceClientConfig, $requestConfigFnName(this, durationSeconds))") } } diff --git a/services/polly/common/test/aws/sdk/kotlin/services/polly/PollyTest.kt b/services/polly/common/test/aws/sdk/kotlin/services/polly/PollyTest.kt index 526642ef8bf..f1a383b78df 100644 --- a/services/polly/common/test/aws/sdk/kotlin/services/polly/PollyTest.kt +++ b/services/polly/common/test/aws/sdk/kotlin/services/polly/PollyTest.kt @@ -34,7 +34,7 @@ class PollyPresignerTest { assertEquals(HttpMethod.GET, presignedRequest.method) assertTrue(presignedRequest.headers.entries().size == 1) assertEquals("polly.us-east-2.amazonaws.com", presignedRequest.headers["Host"]) - val parsedUrl = Url.parse(presignedRequest.url) + val parsedUrl = presignedRequest.url assertEquals("/v1/speech", parsedUrl.path) val expectedQueryParameters = setOf("OutputFormat", "Text", "VoiceId", "X-Amz-Algorithm", "X-Amz-Credential", "X-Amz-Date", "X-Amz-SignedHeaders", "X-Amz-Expires", "X-Amz-Signature") assertEquals(expectedQueryParameters, parsedUrl.parameters.entries().map { it.key }.toSet()) From 068fc4e4b8edd6770da6c8e4acb7c6099d9015ad Mon Sep 17 00:00:00 2001 From: Ken Gilmer Date: Mon, 23 Aug 2021 15:20:07 -0700 Subject: [PATCH 2/5] Pass HttpRequest back to client, remove type PresignRequest. --- .../aws/sdk/kotlin/runtime/auth/Presigner.kt | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/aws-runtime/auth/common/src/aws/sdk/kotlin/runtime/auth/Presigner.kt b/aws-runtime/auth/common/src/aws/sdk/kotlin/runtime/auth/Presigner.kt index 5befeaf289c..1822113ac7d 100644 --- a/aws-runtime/auth/common/src/aws/sdk/kotlin/runtime/auth/Presigner.kt +++ b/aws-runtime/auth/common/src/aws/sdk/kotlin/runtime/auth/Presigner.kt @@ -10,16 +10,14 @@ import aws.sdk.kotlin.runtime.crt.toCrtHeaders import aws.sdk.kotlin.runtime.crt.toSdkHeaders import aws.sdk.kotlin.runtime.endpoint.EndpointResolver import aws.smithy.kotlin.runtime.http.Headers +import aws.smithy.kotlin.runtime.http.HttpBody import aws.smithy.kotlin.runtime.http.HttpMethod import aws.smithy.kotlin.runtime.http.Protocol import aws.smithy.kotlin.runtime.http.QueryParameters import aws.smithy.kotlin.runtime.http.Url import aws.smithy.kotlin.runtime.http.request.HttpRequest -import aws.smithy.kotlin.runtime.http.request.HttpRequestBuilder import aws.smithy.kotlin.runtime.http.util.splitAsQueryParameters import aws.smithy.kotlin.runtime.util.InternalApi -import aws.smithy.kotlin.runtime.util.text.splitAsQueryString -import kotlin.math.sign /** * The service configuration details for a presigned request @@ -101,15 +99,21 @@ public suspend fun createPresignedRequest(serviceConfig: ServicePresignConfig, r ) val signedRequest = AwsSigner.signRequest(request, signingConfig) + // The signer returns the path as an encoded string, we need to partially + // decode this to load into the [HttpRequest] type. val path = signedRequest.encodedPath.substringBefore('?') - val params = signedRequest.encodedPath.substring(path.length + 1).splitAsQueryParameters() + val encodedParams = signedRequest.encodedPath.substring(path.length + 1).splitAsQueryParameters() - return HttpRequestBuilder().apply { - this.url.host = unsignedUrl.host - this.url.path = path - this.url.parameters.appendAll(params) - this.url.scheme = unsignedUrl.scheme - this.headers.appendAll(signedRequest.headers.toSdkHeaders()) - this.method = HttpMethod.parse(signedRequest.method) - }.build() + return HttpRequest( + method = HttpMethod.parse(signedRequest.method), + url = Url( + scheme = Protocol.HTTPS, + host = endpoint.hostname, + path = path, + parameters = encodedParams, + encodeParameters = false + ), + headers = signedRequest.headers.toSdkHeaders(), + body = HttpBody.Empty + ) } From afadbdb255ef1a0b6494fb599cdb738288248ebb Mon Sep 17 00:00:00 2001 From: Ken Gilmer Date: Mon, 23 Aug 2021 15:41:25 -0700 Subject: [PATCH 3/5] cleanup --- .../aws/sdk/kotlin/runtime/auth/Presigner.kt | 10 ++++--- .../kotlin/codegen/PresignerGeneratorTest.kt | 26 +++++++++---------- .../sdk/kotlin/services/polly/PollyTest.kt | 6 ++--- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/aws-runtime/auth/common/src/aws/sdk/kotlin/runtime/auth/Presigner.kt b/aws-runtime/auth/common/src/aws/sdk/kotlin/runtime/auth/Presigner.kt index 1822113ac7d..3f3b22a9be3 100644 --- a/aws-runtime/auth/common/src/aws/sdk/kotlin/runtime/auth/Presigner.kt +++ b/aws-runtime/auth/common/src/aws/sdk/kotlin/runtime/auth/Presigner.kt @@ -5,7 +5,6 @@ import aws.sdk.kotlin.crt.auth.signing.AwsSignedBodyHeaderType import aws.sdk.kotlin.crt.auth.signing.AwsSignedBodyValue import aws.sdk.kotlin.crt.auth.signing.AwsSigner import aws.sdk.kotlin.crt.auth.signing.AwsSigningConfig -import aws.sdk.kotlin.crt.http.HttpRequest as CrtHttpRequest import aws.sdk.kotlin.runtime.crt.toCrtHeaders import aws.sdk.kotlin.runtime.crt.toSdkHeaders import aws.sdk.kotlin.runtime.endpoint.EndpointResolver @@ -18,6 +17,7 @@ import aws.smithy.kotlin.runtime.http.Url import aws.smithy.kotlin.runtime.http.request.HttpRequest import aws.smithy.kotlin.runtime.http.util.splitAsQueryParameters import aws.smithy.kotlin.runtime.util.InternalApi +import aws.sdk.kotlin.crt.http.HttpRequest as CrtHttpRequest /** * The service configuration details for a presigned request @@ -99,10 +99,12 @@ public suspend fun createPresignedRequest(serviceConfig: ServicePresignConfig, r ) val signedRequest = AwsSigner.signRequest(request, signingConfig) - // The signer returns the path as an encoded string, we need to partially - // decode this to load into the [HttpRequest] type. + // The signer returns the path as an encoded string, we need to partially decode this to load into [HttpRequest]. val path = signedRequest.encodedPath.substringBefore('?') - val encodedParams = signedRequest.encodedPath.substring(path.length + 1).splitAsQueryParameters() + val encodedParams = signedRequest + .encodedPath + .substring(path.length + 1) + .splitAsQueryParameters() return HttpRequest( method = HttpMethod.parse(signedRequest.method), diff --git a/codegen/smithy-aws-kotlin-codegen/src/test/kotlin/aws/sdk/kotlin/codegen/PresignerGeneratorTest.kt b/codegen/smithy-aws-kotlin-codegen/src/test/kotlin/aws/sdk/kotlin/codegen/PresignerGeneratorTest.kt index 476fe494225..c52a4039a65 100644 --- a/codegen/smithy-aws-kotlin-codegen/src/test/kotlin/aws/sdk/kotlin/codegen/PresignerGeneratorTest.kt +++ b/codegen/smithy-aws-kotlin-codegen/src/test/kotlin/aws/sdk/kotlin/codegen/PresignerGeneratorTest.kt @@ -89,7 +89,6 @@ class PresignerGeneratorTest { import aws.sdk.kotlin.runtime.ClientException import aws.sdk.kotlin.runtime.auth.CredentialsProvider import aws.sdk.kotlin.runtime.auth.DefaultChainCredentialsProvider - import aws.sdk.kotlin.runtime.auth.PresignedRequest import aws.sdk.kotlin.runtime.auth.PresignedRequestConfig import aws.sdk.kotlin.runtime.auth.ServicePresignConfig import aws.sdk.kotlin.runtime.auth.SigningLocation @@ -97,6 +96,7 @@ class PresignerGeneratorTest { import aws.sdk.kotlin.runtime.endpoint.EndpointResolver import aws.smithy.kotlin.runtime.client.ExecutionContext import aws.smithy.kotlin.runtime.http.QueryParameters + import aws.smithy.kotlin.runtime.http.request.HttpRequest import smithy.kotlin.traits.internal.DefaultEndpointResolver import smithy.kotlin.traits.model.GetFooRequest import smithy.kotlin.traits.model.PostFooRequest @@ -109,9 +109,9 @@ class PresignerGeneratorTest { * Presign a [GetFooRequest] using a [ServicePresignConfig]. * @param serviceClientConfig the client configuration used to generate the presigned request * @param durationSeconds the amount of time from signing for which the request is valid, with seconds granularity. - * @return The [PresignedRequest] that can be invoked within the specified time window. + * @return The [HttpRequest] that can be invoked within the specified time window. */ - suspend fun GetFooRequest.presign(serviceClientConfig: ServicePresignConfig, durationSeconds: ULong): PresignedRequest { + suspend fun GetFooRequest.presign(serviceClientConfig: ServicePresignConfig, durationSeconds: ULong): HttpRequest { return createPresignedRequest(serviceClientConfig, getFooPresignConfig(this, durationSeconds)) } @@ -119,9 +119,9 @@ class PresignerGeneratorTest { * Presign a [GetFooRequest] using a [TestClient]. * @param serviceClient the client providing properties used to generate the presigned request. * @param durationSeconds the amount of time from signing for which the request is valid, with seconds granularity. - * @return The [PresignedRequest] that can be invoked within the specified time window. + * @return The [HttpRequest] that can be invoked within the specified time window. */ - suspend fun GetFooRequest.presign(serviceClient: TestClient, durationSeconds: ULong): PresignedRequest { + suspend fun GetFooRequest.presign(serviceClient: TestClient, durationSeconds: ULong): HttpRequest { val serviceClientConfig = TestPresignConfig { credentialsProvider = serviceClient.config.credentialsProvider ?: DefaultChainCredentialsProvider() endpointResolver = serviceClient.config.endpointResolver ?: DefaultEndpointResolver() @@ -147,9 +147,9 @@ class PresignerGeneratorTest { * Presign a [PostFooRequest] using a [ServicePresignConfig]. * @param serviceClientConfig the client configuration used to generate the presigned request * @param durationSeconds the amount of time from signing for which the request is valid, with seconds granularity. - * @return The [PresignedRequest] that can be invoked within the specified time window. + * @return The [HttpRequest] that can be invoked within the specified time window. */ - suspend fun PostFooRequest.presign(serviceClientConfig: ServicePresignConfig, durationSeconds: ULong): PresignedRequest { + suspend fun PostFooRequest.presign(serviceClientConfig: ServicePresignConfig, durationSeconds: ULong): HttpRequest { return createPresignedRequest(serviceClientConfig, postFooPresignConfig(this, durationSeconds)) } @@ -157,9 +157,9 @@ class PresignerGeneratorTest { * Presign a [PostFooRequest] using a [TestClient]. * @param serviceClient the client providing properties used to generate the presigned request. * @param durationSeconds the amount of time from signing for which the request is valid, with seconds granularity. - * @return The [PresignedRequest] that can be invoked within the specified time window. + * @return The [HttpRequest] that can be invoked within the specified time window. */ - suspend fun PostFooRequest.presign(serviceClient: TestClient, durationSeconds: ULong): PresignedRequest { + suspend fun PostFooRequest.presign(serviceClient: TestClient, durationSeconds: ULong): HttpRequest { val serviceClientConfig = TestPresignConfig { credentialsProvider = serviceClient.config.credentialsProvider ?: DefaultChainCredentialsProvider() endpointResolver = serviceClient.config.endpointResolver ?: DefaultEndpointResolver() @@ -185,9 +185,9 @@ class PresignerGeneratorTest { * Presign a [PutFooRequest] using a [ServicePresignConfig]. * @param serviceClientConfig the client configuration used to generate the presigned request * @param durationSeconds the amount of time from signing for which the request is valid, with seconds granularity. - * @return The [PresignedRequest] that can be invoked within the specified time window. + * @return The [HttpRequest] that can be invoked within the specified time window. */ - suspend fun PutFooRequest.presign(serviceClientConfig: ServicePresignConfig, durationSeconds: ULong): PresignedRequest { + suspend fun PutFooRequest.presign(serviceClientConfig: ServicePresignConfig, durationSeconds: ULong): HttpRequest { return createPresignedRequest(serviceClientConfig, putFooPresignConfig(this, durationSeconds)) } @@ -195,9 +195,9 @@ class PresignerGeneratorTest { * Presign a [PutFooRequest] using a [TestClient]. * @param serviceClient the client providing properties used to generate the presigned request. * @param durationSeconds the amount of time from signing for which the request is valid, with seconds granularity. - * @return The [PresignedRequest] that can be invoked within the specified time window. + * @return The [HttpRequest] that can be invoked within the specified time window. */ - suspend fun PutFooRequest.presign(serviceClient: TestClient, durationSeconds: ULong): PresignedRequest { + suspend fun PutFooRequest.presign(serviceClient: TestClient, durationSeconds: ULong): HttpRequest { val serviceClientConfig = TestPresignConfig { credentialsProvider = serviceClient.config.credentialsProvider ?: DefaultChainCredentialsProvider() endpointResolver = serviceClient.config.endpointResolver ?: DefaultEndpointResolver() diff --git a/services/polly/common/test/aws/sdk/kotlin/services/polly/PollyTest.kt b/services/polly/common/test/aws/sdk/kotlin/services/polly/PollyTest.kt index f1a383b78df..31df18bc4aa 100644 --- a/services/polly/common/test/aws/sdk/kotlin/services/polly/PollyTest.kt +++ b/services/polly/common/test/aws/sdk/kotlin/services/polly/PollyTest.kt @@ -6,7 +6,6 @@ import aws.sdk.kotlin.services.polly.model.OutputFormat import aws.sdk.kotlin.services.polly.model.SynthesizeSpeechRequest import aws.sdk.kotlin.services.polly.model.VoiceId import aws.smithy.kotlin.runtime.http.HttpMethod -import aws.smithy.kotlin.runtime.http.Url import org.junit.jupiter.api.Test import kotlin.test.assertEquals import kotlin.test.assertTrue @@ -34,9 +33,8 @@ class PollyPresignerTest { assertEquals(HttpMethod.GET, presignedRequest.method) assertTrue(presignedRequest.headers.entries().size == 1) assertEquals("polly.us-east-2.amazonaws.com", presignedRequest.headers["Host"]) - val parsedUrl = presignedRequest.url - assertEquals("/v1/speech", parsedUrl.path) + assertEquals("/v1/speech", presignedRequest.url.path) val expectedQueryParameters = setOf("OutputFormat", "Text", "VoiceId", "X-Amz-Algorithm", "X-Amz-Credential", "X-Amz-Date", "X-Amz-SignedHeaders", "X-Amz-Expires", "X-Amz-Signature") - assertEquals(expectedQueryParameters, parsedUrl.parameters.entries().map { it.key }.toSet()) + assertEquals(expectedQueryParameters, presignedRequest.url.parameters.entries().map { it.key }.toSet()) } } From 35a7650e8c334e719172f11bf0f0e5e3d7c3a493 Mon Sep 17 00:00:00 2001 From: Ken Gilmer Date: Tue, 24 Aug 2021 09:05:57 -0700 Subject: [PATCH 4/5] Use existing functions to parse encoded url --- .../src/aws/sdk/kotlin/runtime/auth/Presigner.kt | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/aws-runtime/auth/common/src/aws/sdk/kotlin/runtime/auth/Presigner.kt b/aws-runtime/auth/common/src/aws/sdk/kotlin/runtime/auth/Presigner.kt index 3f3b22a9be3..3914830ee54 100644 --- a/aws-runtime/auth/common/src/aws/sdk/kotlin/runtime/auth/Presigner.kt +++ b/aws-runtime/auth/common/src/aws/sdk/kotlin/runtime/auth/Presigner.kt @@ -5,6 +5,8 @@ import aws.sdk.kotlin.crt.auth.signing.AwsSignedBodyHeaderType import aws.sdk.kotlin.crt.auth.signing.AwsSignedBodyValue import aws.sdk.kotlin.crt.auth.signing.AwsSigner import aws.sdk.kotlin.crt.auth.signing.AwsSigningConfig +import aws.sdk.kotlin.runtime.crt.path +import aws.sdk.kotlin.runtime.crt.queryParameters import aws.sdk.kotlin.runtime.crt.toCrtHeaders import aws.sdk.kotlin.runtime.crt.toSdkHeaders import aws.sdk.kotlin.runtime.endpoint.EndpointResolver @@ -99,20 +101,13 @@ public suspend fun createPresignedRequest(serviceConfig: ServicePresignConfig, r ) val signedRequest = AwsSigner.signRequest(request, signingConfig) - // The signer returns the path as an encoded string, we need to partially decode this to load into [HttpRequest]. - val path = signedRequest.encodedPath.substringBefore('?') - val encodedParams = signedRequest - .encodedPath - .substring(path.length + 1) - .splitAsQueryParameters() - return HttpRequest( method = HttpMethod.parse(signedRequest.method), url = Url( scheme = Protocol.HTTPS, host = endpoint.hostname, - path = path, - parameters = encodedParams, + path = signedRequest.path(), + parameters = signedRequest.queryParameters() ?: QueryParameters.Empty, encodeParameters = false ), headers = signedRequest.headers.toSdkHeaders(), From 7f8712364ccd0f00bb4f477673d6ed2ce4e97c56 Mon Sep 17 00:00:00 2001 From: Ken Gilmer Date: Tue, 24 Aug 2021 13:29:34 -0700 Subject: [PATCH 5/5] linter --- .../auth/common/src/aws/sdk/kotlin/runtime/auth/Presigner.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/aws-runtime/auth/common/src/aws/sdk/kotlin/runtime/auth/Presigner.kt b/aws-runtime/auth/common/src/aws/sdk/kotlin/runtime/auth/Presigner.kt index 3914830ee54..6cc306eede3 100644 --- a/aws-runtime/auth/common/src/aws/sdk/kotlin/runtime/auth/Presigner.kt +++ b/aws-runtime/auth/common/src/aws/sdk/kotlin/runtime/auth/Presigner.kt @@ -17,7 +17,6 @@ import aws.smithy.kotlin.runtime.http.Protocol import aws.smithy.kotlin.runtime.http.QueryParameters import aws.smithy.kotlin.runtime.http.Url import aws.smithy.kotlin.runtime.http.request.HttpRequest -import aws.smithy.kotlin.runtime.http.util.splitAsQueryParameters import aws.smithy.kotlin.runtime.util.InternalApi import aws.sdk.kotlin.crt.http.HttpRequest as CrtHttpRequest