Skip to content

Commit b4c12e6

Browse files
authored
refactor(rt): Use existing type HttpRequest rather than specific PresignedRequest to represent presigned requests (#292)
1 parent 0aaf0f3 commit b4c12e6

File tree

5 files changed

+45
-50
lines changed

5 files changed

+45
-50
lines changed

aws-runtime/auth/common/src/aws/sdk/kotlin/runtime/auth/Presigner.kt

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,20 @@ import aws.sdk.kotlin.crt.auth.signing.AwsSignedBodyHeaderType
55
import aws.sdk.kotlin.crt.auth.signing.AwsSignedBodyValue
66
import aws.sdk.kotlin.crt.auth.signing.AwsSigner
77
import aws.sdk.kotlin.crt.auth.signing.AwsSigningConfig
8-
import aws.sdk.kotlin.crt.http.HttpRequest
8+
import aws.sdk.kotlin.runtime.crt.path
9+
import aws.sdk.kotlin.runtime.crt.queryParameters
910
import aws.sdk.kotlin.runtime.crt.toCrtHeaders
1011
import aws.sdk.kotlin.runtime.crt.toSdkHeaders
1112
import aws.sdk.kotlin.runtime.endpoint.EndpointResolver
1213
import aws.smithy.kotlin.runtime.http.Headers
14+
import aws.smithy.kotlin.runtime.http.HttpBody
1315
import aws.smithy.kotlin.runtime.http.HttpMethod
1416
import aws.smithy.kotlin.runtime.http.Protocol
1517
import aws.smithy.kotlin.runtime.http.QueryParameters
1618
import aws.smithy.kotlin.runtime.http.Url
19+
import aws.smithy.kotlin.runtime.http.request.HttpRequest
1720
import aws.smithy.kotlin.runtime.util.InternalApi
21+
import aws.sdk.kotlin.crt.http.HttpRequest as CrtHttpRequest
1822

1923
/**
2024
* The service configuration details for a presigned request
@@ -63,26 +67,14 @@ public data class PresignedRequestConfig(
6367
public val additionalHeaders: Headers = Headers.Empty
6468
)
6569

66-
/**
67-
* Properties of an HTTP request that has been presigned
68-
* @property method HTTP method to use when initiating the request
69-
* @property url HTTP url of the presigned request
70-
* @property headers Headers that must be sent with the request
71-
*/
72-
public data class PresignedRequest(
73-
val method: HttpMethod,
74-
val url: String,
75-
val headers: Headers
76-
)
77-
7870
/**
7971
* Generate a presigned request given the service and operation configurations.
8072
* @param serviceConfig The service configuration to use in signing the request
8173
* @param requestConfig The presign configuration to use in signing the request
82-
* @return a [PresignedRequest] that can be executed by any HTTP client within the specified duration.
74+
* @return a [HttpRequest] that can be executed by any HTTP client within the specified duration.
8375
*/
8476
@InternalApi
85-
public suspend fun createPresignedRequest(serviceConfig: ServicePresignConfig, requestConfig: PresignedRequestConfig): PresignedRequest {
77+
public suspend fun createPresignedRequest(serviceConfig: ServicePresignConfig, requestConfig: PresignedRequestConfig): HttpRequest {
8678
val crtCredentials = serviceConfig.credentialsProvider.getCredentials().toCrt()
8779
val endpoint = serviceConfig.endpointResolver.resolve(serviceConfig.serviceId, serviceConfig.region)
8880

@@ -96,22 +88,28 @@ public suspend fun createPresignedRequest(serviceConfig: ServicePresignConfig, r
9688
expirationInSeconds = requestConfig.durationSeconds
9789
}
9890

99-
val url = Url(Protocol.HTTPS, endpoint.hostname, path = requestConfig.path, parameters = requestConfig.queryString)
91+
val unsignedUrl = Url(Protocol.HTTPS, endpoint.hostname, path = requestConfig.path, parameters = requestConfig.queryString)
10092

101-
val headers = aws.sdk.kotlin.crt.http.Headers.build {
102-
append("Host", endpoint.hostname)
103-
appendAll(requestConfig.additionalHeaders.toCrtHeaders())
104-
}
105-
val request = HttpRequest(
93+
val request = CrtHttpRequest(
10694
requestConfig.method.name,
107-
url.encodedPath,
108-
headers
95+
unsignedUrl.encodedPath,
96+
aws.sdk.kotlin.crt.http.Headers.build {
97+
append("Host", endpoint.hostname)
98+
appendAll(requestConfig.additionalHeaders.toCrtHeaders())
99+
}
109100
)
110101
val signedRequest = AwsSigner.signRequest(request, signingConfig)
111102

112-
return PresignedRequest(
113-
requestConfig.method,
114-
"${endpoint.protocol}://${endpoint.hostname}${signedRequest.encodedPath}",
115-
signedRequest.headers.toSdkHeaders()
103+
return HttpRequest(
104+
method = HttpMethod.parse(signedRequest.method),
105+
url = Url(
106+
scheme = Protocol.HTTPS,
107+
host = endpoint.hostname,
108+
path = signedRequest.path(),
109+
parameters = signedRequest.queryParameters() ?: QueryParameters.Empty,
110+
encodeParameters = false
111+
),
112+
headers = signedRequest.headers.toSdkHeaders(),
113+
body = HttpBody.Empty
116114
)
117115
}

codegen/smithy-aws-kotlin-codegen/src/main/kotlin/aws/sdk/kotlin/codegen/AwsRuntimeTypes.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ object AwsRuntimeTypes {
4343
val CredentialsProvider = runtimeSymbol("CredentialsProvider", AwsKotlinDependency.AWS_AUTH)
4444
val createPresignedRequest = runtimeSymbol("createPresignedRequest", AwsKotlinDependency.AWS_AUTH)
4545
val DefaultChainCredentialsProvider = runtimeSymbol("DefaultChainCredentialsProvider", AwsKotlinDependency.AWS_AUTH)
46-
val PresignedRequest = runtimeSymbol("PresignedRequest", AwsKotlinDependency.AWS_AUTH)
4746
val PresignedRequestConfig = runtimeSymbol("PresignedRequestConfig", AwsKotlinDependency.AWS_AUTH)
4847
val ServicePresignConfig = runtimeSymbol("ServicePresignConfig", AwsKotlinDependency.AWS_AUTH)
4948
val SigningLocation = runtimeSymbol("SigningLocation", AwsKotlinDependency.AWS_AUTH)

codegen/smithy-aws-kotlin-codegen/src/main/kotlin/aws/sdk/kotlin/codegen/PresignerGenerator.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,11 @@ class PresignerGenerator : KotlinIntegration {
7575
// Symbols which should be imported
7676
private val presignerRuntimeSymbols = setOf(
7777
// smithy-kotlin types
78+
RuntimeTypes.Http.Request.HttpRequest,
7879
RuntimeTypes.Core.ExecutionContext,
7980
// AWS types
8081
AwsRuntimeTypes.Auth.CredentialsProvider,
8182
AwsRuntimeTypes.Auth.DefaultChainCredentialsProvider,
82-
AwsRuntimeTypes.Auth.PresignedRequest,
8383
AwsRuntimeTypes.Auth.PresignedRequestConfig,
8484
AwsRuntimeTypes.Auth.ServicePresignConfig,
8585
AwsRuntimeTypes.Auth.SigningLocation,
@@ -327,10 +327,10 @@ class PresignerGenerator : KotlinIntegration {
327327
write("Presign a [$requestTypeName] using a [$serviceClientTypeName].")
328328
write("@param serviceClient the client providing properties used to generate the presigned request.")
329329
write("@param durationSeconds the amount of time from signing for which the request is valid, with seconds granularity.")
330-
write("@return The [PresignedRequest] that can be invoked within the specified time window.")
330+
write("@return The [HttpRequest] that can be invoked within the specified time window.")
331331
}
332332
// FIXME ~ Replace or add additional function, swap ULong type for kotlin.time.Duration when type becomes stable
333-
writer.withBlock("suspend fun $requestTypeName.presign(serviceClient: $serviceClientTypeName, durationSeconds: ULong): PresignedRequest {", "}\n") {
333+
writer.withBlock("suspend fun $requestTypeName.presign(serviceClient: $serviceClientTypeName, durationSeconds: ULong): HttpRequest {", "}\n") {
334334
withBlock("val serviceClientConfig = $presignConfigTypeName {", "}") {
335335
write("credentialsProvider = serviceClient.config.credentialsProvider ?: DefaultChainCredentialsProvider()")
336336
write("endpointResolver = serviceClient.config.endpointResolver ?: DefaultEndpointResolver()")
@@ -345,10 +345,10 @@ class PresignerGenerator : KotlinIntegration {
345345
write("Presign a [$requestTypeName] using a [ServicePresignConfig].")
346346
write("@param serviceClientConfig the client configuration used to generate the presigned request")
347347
write("@param durationSeconds the amount of time from signing for which the request is valid, with seconds granularity.")
348-
write("@return The [PresignedRequest] that can be invoked within the specified time window.")
348+
write("@return The [HttpRequest] that can be invoked within the specified time window.")
349349
}
350350
// FIXME ~ Replace or add additional function, swap ULong type for kotlin.time.Duration when type becomes stable
351-
writer.withBlock("suspend fun $requestTypeName.presign(serviceClientConfig: ServicePresignConfig, durationSeconds: ULong): PresignedRequest {", "}\n") {
351+
writer.withBlock("suspend fun $requestTypeName.presign(serviceClientConfig: ServicePresignConfig, durationSeconds: ULong): HttpRequest {", "}\n") {
352352
write("return createPresignedRequest(serviceClientConfig, $requestConfigFnName(this, durationSeconds))")
353353
}
354354
}

codegen/smithy-aws-kotlin-codegen/src/test/kotlin/aws/sdk/kotlin/codegen/PresignerGeneratorTest.kt

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -89,14 +89,14 @@ class PresignerGeneratorTest {
8989
import aws.sdk.kotlin.runtime.ClientException
9090
import aws.sdk.kotlin.runtime.auth.CredentialsProvider
9191
import aws.sdk.kotlin.runtime.auth.DefaultChainCredentialsProvider
92-
import aws.sdk.kotlin.runtime.auth.PresignedRequest
9392
import aws.sdk.kotlin.runtime.auth.PresignedRequestConfig
9493
import aws.sdk.kotlin.runtime.auth.ServicePresignConfig
9594
import aws.sdk.kotlin.runtime.auth.SigningLocation
9695
import aws.sdk.kotlin.runtime.auth.createPresignedRequest
9796
import aws.sdk.kotlin.runtime.endpoint.EndpointResolver
9897
import aws.smithy.kotlin.runtime.client.ExecutionContext
9998
import aws.smithy.kotlin.runtime.http.QueryParameters
99+
import aws.smithy.kotlin.runtime.http.request.HttpRequest
100100
import smithy.kotlin.traits.internal.DefaultEndpointResolver
101101
import smithy.kotlin.traits.model.GetFooRequest
102102
import smithy.kotlin.traits.model.PostFooRequest
@@ -109,19 +109,19 @@ class PresignerGeneratorTest {
109109
* Presign a [GetFooRequest] using a [ServicePresignConfig].
110110
* @param serviceClientConfig the client configuration used to generate the presigned request
111111
* @param durationSeconds the amount of time from signing for which the request is valid, with seconds granularity.
112-
* @return The [PresignedRequest] that can be invoked within the specified time window.
112+
* @return The [HttpRequest] that can be invoked within the specified time window.
113113
*/
114-
suspend fun GetFooRequest.presign(serviceClientConfig: ServicePresignConfig, durationSeconds: ULong): PresignedRequest {
114+
suspend fun GetFooRequest.presign(serviceClientConfig: ServicePresignConfig, durationSeconds: ULong): HttpRequest {
115115
return createPresignedRequest(serviceClientConfig, getFooPresignConfig(this, durationSeconds))
116116
}
117117
118118
/**
119119
* Presign a [GetFooRequest] using a [TestClient].
120120
* @param serviceClient the client providing properties used to generate the presigned request.
121121
* @param durationSeconds the amount of time from signing for which the request is valid, with seconds granularity.
122-
* @return The [PresignedRequest] that can be invoked within the specified time window.
122+
* @return The [HttpRequest] that can be invoked within the specified time window.
123123
*/
124-
suspend fun GetFooRequest.presign(serviceClient: TestClient, durationSeconds: ULong): PresignedRequest {
124+
suspend fun GetFooRequest.presign(serviceClient: TestClient, durationSeconds: ULong): HttpRequest {
125125
val serviceClientConfig = TestPresignConfig {
126126
credentialsProvider = serviceClient.config.credentialsProvider ?: DefaultChainCredentialsProvider()
127127
endpointResolver = serviceClient.config.endpointResolver ?: DefaultEndpointResolver()
@@ -147,19 +147,19 @@ class PresignerGeneratorTest {
147147
* Presign a [PostFooRequest] using a [ServicePresignConfig].
148148
* @param serviceClientConfig the client configuration used to generate the presigned request
149149
* @param durationSeconds the amount of time from signing for which the request is valid, with seconds granularity.
150-
* @return The [PresignedRequest] that can be invoked within the specified time window.
150+
* @return The [HttpRequest] that can be invoked within the specified time window.
151151
*/
152-
suspend fun PostFooRequest.presign(serviceClientConfig: ServicePresignConfig, durationSeconds: ULong): PresignedRequest {
152+
suspend fun PostFooRequest.presign(serviceClientConfig: ServicePresignConfig, durationSeconds: ULong): HttpRequest {
153153
return createPresignedRequest(serviceClientConfig, postFooPresignConfig(this, durationSeconds))
154154
}
155155
156156
/**
157157
* Presign a [PostFooRequest] using a [TestClient].
158158
* @param serviceClient the client providing properties used to generate the presigned request.
159159
* @param durationSeconds the amount of time from signing for which the request is valid, with seconds granularity.
160-
* @return The [PresignedRequest] that can be invoked within the specified time window.
160+
* @return The [HttpRequest] that can be invoked within the specified time window.
161161
*/
162-
suspend fun PostFooRequest.presign(serviceClient: TestClient, durationSeconds: ULong): PresignedRequest {
162+
suspend fun PostFooRequest.presign(serviceClient: TestClient, durationSeconds: ULong): HttpRequest {
163163
val serviceClientConfig = TestPresignConfig {
164164
credentialsProvider = serviceClient.config.credentialsProvider ?: DefaultChainCredentialsProvider()
165165
endpointResolver = serviceClient.config.endpointResolver ?: DefaultEndpointResolver()
@@ -185,19 +185,19 @@ class PresignerGeneratorTest {
185185
* Presign a [PutFooRequest] using a [ServicePresignConfig].
186186
* @param serviceClientConfig the client configuration used to generate the presigned request
187187
* @param durationSeconds the amount of time from signing for which the request is valid, with seconds granularity.
188-
* @return The [PresignedRequest] that can be invoked within the specified time window.
188+
* @return The [HttpRequest] that can be invoked within the specified time window.
189189
*/
190-
suspend fun PutFooRequest.presign(serviceClientConfig: ServicePresignConfig, durationSeconds: ULong): PresignedRequest {
190+
suspend fun PutFooRequest.presign(serviceClientConfig: ServicePresignConfig, durationSeconds: ULong): HttpRequest {
191191
return createPresignedRequest(serviceClientConfig, putFooPresignConfig(this, durationSeconds))
192192
}
193193
194194
/**
195195
* Presign a [PutFooRequest] using a [TestClient].
196196
* @param serviceClient the client providing properties used to generate the presigned request.
197197
* @param durationSeconds the amount of time from signing for which the request is valid, with seconds granularity.
198-
* @return The [PresignedRequest] that can be invoked within the specified time window.
198+
* @return The [HttpRequest] that can be invoked within the specified time window.
199199
*/
200-
suspend fun PutFooRequest.presign(serviceClient: TestClient, durationSeconds: ULong): PresignedRequest {
200+
suspend fun PutFooRequest.presign(serviceClient: TestClient, durationSeconds: ULong): HttpRequest {
201201
val serviceClientConfig = TestPresignConfig {
202202
credentialsProvider = serviceClient.config.credentialsProvider ?: DefaultChainCredentialsProvider()
203203
endpointResolver = serviceClient.config.endpointResolver ?: DefaultEndpointResolver()

services/polly/common/test/aws/sdk/kotlin/services/polly/PollyTest.kt

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import aws.sdk.kotlin.services.polly.model.OutputFormat
66
import aws.sdk.kotlin.services.polly.model.SynthesizeSpeechRequest
77
import aws.sdk.kotlin.services.polly.model.VoiceId
88
import aws.smithy.kotlin.runtime.http.HttpMethod
9-
import aws.smithy.kotlin.runtime.http.Url
109
import org.junit.jupiter.api.Test
1110
import kotlin.test.assertEquals
1211
import kotlin.test.assertTrue
@@ -34,9 +33,8 @@ class PollyPresignerTest {
3433
assertEquals(HttpMethod.GET, presignedRequest.method)
3534
assertTrue(presignedRequest.headers.entries().size == 1)
3635
assertEquals("polly.us-east-2.amazonaws.com", presignedRequest.headers["Host"])
37-
val parsedUrl = Url.parse(presignedRequest.url)
38-
assertEquals("/v1/speech", parsedUrl.path)
36+
assertEquals("/v1/speech", presignedRequest.url.path)
3937
val expectedQueryParameters = setOf("OutputFormat", "Text", "VoiceId", "X-Amz-Algorithm", "X-Amz-Credential", "X-Amz-Date", "X-Amz-SignedHeaders", "X-Amz-Expires", "X-Amz-Signature")
40-
assertEquals(expectedQueryParameters, parsedUrl.parameters.entries().map { it.key }.toSet())
38+
assertEquals(expectedQueryParameters, presignedRequest.url.parameters.entries().map { it.key }.toSet())
4139
}
4240
}

0 commit comments

Comments
 (0)