Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: expose presign / presignURL methods in Models.swift to service client object #1198

Merged
merged 11 commits into from
Nov 6, 2023
18 changes: 18 additions & 0 deletions Sources/Services/AWSPolly/PollyClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -481,3 +481,21 @@ extension PollyClient: PollyClientProtocol {
}

}

extension PollyClient {
public func getPresignedURLForSynthesizeSpeech(input: SynthesizeSpeechInput, expiration: Foundation.TimeInterval) async throws -> Foundation.URL {
guard let presignedURL = try await input.presignURL(config: config, expiration: expiration) else {
dayaffe marked this conversation as resolved.
Show resolved Hide resolved
throw ClientError.unknownError("Returned URL from input.presignURL() was nil for the operation SynthesizeSpeech.")
}
return presignedURL
}
}

extension PollyClient {
public func presignRequestForSynthesizeSpeech(input: SynthesizeSpeechInput, expiration: Foundation.TimeInterval) async throws -> URLRequest {
sichanyoo marked this conversation as resolved.
Show resolved Hide resolved
guard let presignedRequest = try await input.presign(config: config, expiration: expiration) else {
sichanyoo marked this conversation as resolved.
Show resolved Hide resolved
throw ClientError.unknownError("Returned request from input.presign() was nil for the operation SynthesizeSpeech.")
}
return try await presignedRequest.toURLRequest()
}
}
45 changes: 45 additions & 0 deletions Sources/Services/AWSS3/S3Client.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5023,3 +5023,48 @@ extension S3Client: S3ClientProtocol {
}

}

extension S3Client {
public func getPresignedURLForGetObject(input: GetObjectInput, expiration: Foundation.TimeInterval) async throws -> Foundation.URL {
guard let presignedURL = try await input.presignURL(config: config, expiration: expiration) else {
throw ClientError.unknownError("Returned URL from input.presignURL() was nil for the operation GetObject.")
}
return presignedURL
}
}

extension S3Client {
public func getPresignedURLForPutObject(input: PutObjectInput, expiration: Foundation.TimeInterval) async throws -> Foundation.URL {
guard let presignedURL = try await input.presignURL(config: config, expiration: expiration) else {
throw ClientError.unknownError("Returned URL from input.presignURL() was nil for the operation PutObject.")
}
return presignedURL
}
}

extension S3Client {
public func presignRequestForGetObject(input: GetObjectInput, expiration: Foundation.TimeInterval) async throws -> URLRequest {
guard let presignedRequest = try await input.presign(config: config, expiration: expiration) else {
throw ClientError.unknownError("Returned request from input.presign() was nil for the operation GetObject.")
}
return try await presignedRequest.toURLRequest()
}
}

extension S3Client {
public func presignRequestForPutObject(input: PutObjectInput, expiration: Foundation.TimeInterval) async throws -> URLRequest {
guard let presignedRequest = try await input.presign(config: config, expiration: expiration) else {
throw ClientError.unknownError("Returned request from input.presign() was nil for the operation PutObject.")
}
return try await presignedRequest.toURLRequest()
}
}

extension S3Client {
public func presignRequestForUploadPart(input: UploadPartInput, expiration: Foundation.TimeInterval) async throws -> URLRequest {
guard let presignedRequest = try await input.presign(config: config, expiration: expiration) else {
throw ClientError.unknownError("Returned request from input.presign() was nil for the operation UploadPart.")
}
return try await presignedRequest.toURLRequest()
}
}
9 changes: 9 additions & 0 deletions Sources/Services/AWSSTS/STSClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -462,3 +462,12 @@ extension STSClient: STSClientProtocol {
}

}

extension STSClient {
public func presignRequestForGetCallerIdentity(input: GetCallerIdentityInput, expiration: Foundation.TimeInterval) async throws -> URLRequest {
guard let presignedRequest = try await input.presign(config: config, expiration: expiration) else {
throw ClientError.unknownError("Returned request from input.presign() was nil for the operation GetCallerIdentity.")
sichanyoo marked this conversation as resolved.
Show resolved Hide resolved
}
return try await presignedRequest.toURLRequest()
jbelkins marked this conversation as resolved.
Show resolved Hide resolved
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import software.amazon.smithy.swift.codegen.middleware.MiddlewareExecutionGenera
import software.amazon.smithy.swift.codegen.middleware.MiddlewareStep
import software.amazon.smithy.swift.codegen.middleware.OperationMiddleware
import software.amazon.smithy.swift.codegen.model.expectShape
import software.amazon.smithy.swift.codegen.model.toUpperCamelCase

data class PresignableOperation(
val serviceId: String,
Expand Down Expand Up @@ -50,6 +51,16 @@ class PresignerGenerator : SwiftIntegration {
var serviceConfig = AWSServiceConfig(writer, protoCtx)
renderPresigner(writer, ctx, delegator, op, inputType, serviceConfig)
}
// Expose presign-request as a method for service client object
val symbol = protoCtx.symbolProvider.toSymbol(protoCtx.service)
protoCtx.delegator.useFileWriter("./${ctx.settings.moduleName}/${symbol.name}.swift") { writer ->
renderPresignAPIInServiceClient(writer, symbol.name, op, inputType)
// Add special-case import statement for Linux
writer.write("// In Linux, Foundation.URLRequest is moved to FoundationNetworking.")
sichanyoo marked this conversation as resolved.
Show resolved Hide resolved
writer.write("#if canImport(FoundationNetworking)")
writer.write("import FoundationNetworking")
writer.write("#endif")
}
}
}

Expand Down Expand Up @@ -105,6 +116,26 @@ class PresignerGenerator : SwiftIntegration {
}
}

private fun renderPresignAPIInServiceClient(
writer: SwiftWriter,
clientName: String,
op: OperationShape,
inputType: String
) {
writer.apply {
openBlock("extension $clientName {", "}") {
val params = listOf("input: $inputType", "expiration: Foundation.TimeInterval")
val returnType = "URLRequest"
openBlock("public func presignRequestFor${op.toUpperCamelCase()}(${params.joinToString()}) async throws -> $returnType {", "}") {
jbelkins marked this conversation as resolved.
Show resolved Hide resolved
openBlock("guard let presignedRequest = try await input.presign(config: config, expiration: expiration) else {", "}") {
write("throw ClientError.unknownError(\"Returned request from input.presign() was nil for the operation ${op.toUpperCamelCase()}.\")")
}
write("return try await presignedRequest.toURLRequest()")
}
}
}
}

private fun resolveOperationMiddleware(protocolGenerator: ProtocolGenerator, op: OperationShape, ctx: CodegenContext): OperationMiddleware {
val operationMiddlewareCopy = protocolGenerator.operationMiddleware.clone()
operationMiddlewareCopy.removeMiddleware(op, MiddlewareStep.FINALIZESTEP, "AWSSigningMiddleware")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import software.amazon.smithy.swift.codegen.middleware.MiddlewareExecutionGenera
import software.amazon.smithy.swift.codegen.middleware.MiddlewareStep
import software.amazon.smithy.swift.codegen.middleware.OperationMiddleware
import software.amazon.smithy.swift.codegen.model.expectShape
import software.amazon.smithy.swift.codegen.model.toUpperCamelCase

internal val PRESIGNABLE_URL_OPERATIONS: Map<String, Set<String>> = mapOf(
"com.amazonaws.polly#Parrot_v1" to setOf(
Expand Down Expand Up @@ -70,6 +71,11 @@ class PresignableUrlIntegration(private val presignedOperations: Map<String, Set
val serviceConfig = AWSServiceConfig(writer, protocolGenerationContext)
renderPresigner(writer, ctx, delegator, op, inputType, serviceConfig)
}
// Expose presign-URL as a method for service client object
val symbol = protocolGenerationContext.symbolProvider.toSymbol(protocolGenerationContext.service)
protocolGenerationContext.delegator.useFileWriter("./${ctx.settings.moduleName}/${symbol.name}.swift") { writer ->
renderPresignURLAPIInServiceClient(writer, symbol.name, op, inputType)
}
when (presignableOperation.operationId) {
"com.amazonaws.s3#GetObject", "com.amazonaws.polly#SynthesizeSpeech" -> {
renderMiddlewareClassForQueryString(ctx, delegator, op)
Expand Down Expand Up @@ -144,6 +150,26 @@ class PresignableUrlIntegration(private val presignedOperations: Map<String, Set
}
}

private fun renderPresignURLAPIInServiceClient(
writer: SwiftWriter,
clientName: String,
op: OperationShape,
inputType: String
) {
writer.apply {
openBlock("extension $clientName {", "}") {
val params = listOf("input: $inputType", "expiration: Foundation.TimeInterval")
val returnType = "Foundation.URL"
openBlock("public func getPresignedURLFor${op.toUpperCamelCase()}(${params.joinToString()}) async throws -> $returnType {", "}") {
openBlock("guard let presignedURL = try await input.presignURL(config: config, expiration: expiration) else {", "}") {
write("throw ClientError.unknownError(\"Returned URL from input.presignURL() was nil for the operation ${op.toUpperCamelCase()}.\")")
}
write("return presignedURL")
}
}
}
}

private fun resolveOperationMiddleware(protocolGenerator: ProtocolGenerator, context: ProtocolGenerator.GenerationContext, op: OperationShape): OperationMiddleware {
val inputSymbol = MiddlewareShapeUtils.inputSymbol(context.symbolProvider, context.model, op)
val operationMiddlewareCopy = protocolGenerator.operationMiddleware.clone()
Expand Down