Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

public struct SerializableBodyMiddleware<OperationStackInput: Encodable & Reflection,
OperationStackOutput: HttpResponseBinding,
OperationStackError: HttpResponseBinding>: Middleware {
public let id: Swift.String = "\(String(describing: OperationStackInput.self))BodyMiddleware"

let alwaysSendBody: Bool

public init(alwaysSendBody: Bool = false) {
self.alwaysSendBody = alwaysSendBody
}

public func handle<H>(context: Context,
input: SerializeStepInput<OperationStackInput>,
next: H) -> Swift.Result<OperationOutput<OperationStackOutput>, MError>
where H: Handler,
Self.MInput == H.Input,
Self.MOutput == H.Output,
Self.Context == H.Context,
Self.MError == H.MiddlewareError {
do {
if try alwaysSendBody || !input.operationInput.allPropertiesAreNull() {
let encoder = context.getEncoder()
let data = try encoder.encode(input.operationInput)
let body = HttpBody.data(data)
input.builder.withBody(body)
}
} catch let err {
return .failure(.client(ClientError.serializationFailed(err.localizedDescription)))
}
return next.handle(context: context, input: input)
}

public typealias MInput = SerializeStepInput<OperationStackInput>
public typealias MOutput = OperationOutput<OperationStackOutput>
public typealias Context = HttpContext
public typealias MError = SdkError<OperationStackError>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

public struct URLHostMiddleware<OperationStackInput: Encodable & Reflection,
OperationStackOutput: HttpResponseBinding,
OperationStackError: HttpResponseBinding>: Middleware {
public let id: String = "\(String(describing: OperationStackInput.self))URLHostMiddleware"

let host: String?
let hostPrefix: String?

public init(host: String? = nil, hostPrefix: String? = nil) {
self.host = host
self.hostPrefix = hostPrefix
}

public func handle<H>(context: Context,
input: MInput,
next: H) -> Result<MOutput, MError>
where H: Handler,
Self.MInput == H.Input,
Self.MOutput == H.Output,
Self.Context == H.Context,
Self.MError == H.MiddlewareError {
var copiedContext = context
if let host = host {
copiedContext.attributes.set(key: AttributeKey<String>(name: "Host"),
value: host)
}
if let hostPrefix = hostPrefix {
copiedContext.attributes.set(key: AttributeKey<String>(name: "HostPrefix"),
value: hostPrefix)
}
return next.handle(context: copiedContext, input: input)
}

public typealias MInput = OperationStackInput
public typealias MOutput = OperationOutput<OperationStackOutput>
public typealias Context = HttpContext
public typealias MError = SdkError<OperationStackError>
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ object ClientRuntimeTypes {
val DeserializeMiddleware = runtimeSymbol("DeserializeMiddleware")
val MutateHeadersMiddleware = runtimeSymbol("MutateHeadersMiddleware")
val OperationStack = runtimeSymbol("OperationStack")

val URLHostMiddleware = runtimeSymbol("URLHostMiddleware")
val SerializableBodyMiddleware = runtimeSymbol("SerializableBodyMiddleware")
val NoopHandler = runtimeSymbol("NoopHandler")
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ import software.amazon.smithy.swift.codegen.integration.middlewares.OperationInp
import software.amazon.smithy.swift.codegen.integration.middlewares.handlers.HttpBodyMiddleware
import software.amazon.smithy.swift.codegen.integration.middlewares.handlers.HttpHeaderMiddleware
import software.amazon.smithy.swift.codegen.integration.middlewares.handlers.HttpQueryItemMiddleware
import software.amazon.smithy.swift.codegen.integration.middlewares.handlers.HttpUrlHostMiddleware
import software.amazon.smithy.swift.codegen.integration.middlewares.handlers.HttpUrlPathMiddleware
import software.amazon.smithy.swift.codegen.integration.serde.DynamicNodeDecodingGeneratorStrategy
import software.amazon.smithy.swift.codegen.integration.serde.UnionDecodeGeneratorStrategy
Expand Down Expand Up @@ -130,11 +129,10 @@ abstract class HttpBindingProtocolGenerator : ProtocolGenerator {
continue
}
val httpBindingResolver = getProtocolHttpBindingResolver(ctx, defaultContentType)
HttpUrlHostMiddleware.renderMiddleware(ctx, operation, httpBindingResolver)
HttpUrlPathMiddleware.renderUrlPathMiddleware(ctx, operation, httpBindingResolver)
HttpHeaderMiddleware.renderHeaderMiddleware(ctx, operation, httpBindingResolver, defaultTimestampFormat)
HttpQueryItemMiddleware.renderQueryMiddleware(ctx, operation, httpBindingResolver, defaultTimestampFormat)
HttpBodyMiddleware.renderBodyMiddleware(ctx, operation, httpBindingResolver, httpProtocolBodyMiddleware())
HttpBodyMiddleware.renderBodyMiddleware(ctx, operation, httpBindingResolver)
inputShapesWithHttpBindings.add(inputShapeId)
}
}
Expand Down Expand Up @@ -380,13 +378,12 @@ abstract class HttpBindingProtocolGenerator : ProtocolGenerator {

override fun initializeMiddleware(ctx: ProtocolGenerator.GenerationContext) {
val resolver = getProtocolHttpBindingResolver(ctx, defaultContentType)

for (operation in getHttpBindingOperations(ctx)) {
operationMiddleware.appendMiddleware(operation, IdempotencyTokenMiddleware(ctx.model, ctx.symbolProvider))

operationMiddleware.appendMiddleware(operation, ContentMD5Middleware(ctx.model, ctx.symbolProvider))
operationMiddleware.appendMiddleware(operation, OperationInputUrlPathMiddleware(ctx.model, ctx.symbolProvider, ""))
operationMiddleware.appendMiddleware(operation, OperationInputUrlHostMiddleware(ctx.model, ctx.symbolProvider, ""))
operationMiddleware.appendMiddleware(operation, OperationInputUrlHostMiddleware(ctx.model, ctx.symbolProvider, operation))
operationMiddleware.appendMiddleware(operation, OperationInputHeadersMiddleware(ctx.model, ctx.symbolProvider))
operationMiddleware.appendMiddleware(operation, OperationInputQueryItemMiddleware(ctx.model, ctx.symbolProvider))
operationMiddleware.appendMiddleware(operation, ContentTypeMiddleware(ctx.model, ctx.symbolProvider, resolver.determineRequestContentType(operation)))
Expand Down Expand Up @@ -430,10 +427,6 @@ abstract class HttpBindingProtocolGenerator : ProtocolGenerator {
)
protected abstract fun addProtocolSpecificMiddleware(ctx: ProtocolGenerator.GenerationContext, operation: OperationShape)

open fun httpProtocolBodyMiddleware(): HttpProtocolBodyMiddlewareGeneratorFactory {
return DefaultHttpProtocolBodyMiddlewareGeneratorFactory()
}

/**
* Get the operations with HTTP Bindings.
*
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ class HttpProtocolTestGenerator(
val hostMiddlewares = cloned.middlewares(operation, MiddlewareStep.INITIALIZESTEP)
.filter { it.name.contains("HostMiddleware") }
if (hostMiddlewares.isEmpty()) {
cloned.appendMiddleware(operation, OperationInputUrlHostMiddleware(ctx.model, ctx.symbolProvider, "host: hostOnly"))
cloned.appendMiddleware(operation, OperationInputUrlHostMiddleware(ctx.model, ctx.symbolProvider, operation, true))
}
}
return cloned
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package software.amazon.smithy.swift.codegen.integration.middlewares
import software.amazon.smithy.codegen.core.SymbolProvider
import software.amazon.smithy.model.Model
import software.amazon.smithy.model.shapes.OperationShape
import software.amazon.smithy.swift.codegen.ClientRuntimeTypes
import software.amazon.smithy.swift.codegen.SwiftWriter
import software.amazon.smithy.swift.codegen.integration.middlewares.handlers.MiddlewareShapeUtils
import software.amazon.smithy.swift.codegen.middleware.MiddlewarePosition
Expand All @@ -12,7 +13,7 @@ import software.amazon.smithy.swift.codegen.middleware.MiddlewareStep
class OperationInputBodyMiddleware(
val model: Model,
val symbolProvider: SymbolProvider,
val shouldRender: Boolean = false
val alwaysSendBody: Boolean = false
) : MiddlewareRenderable {

override val name = "OperationInputBodyMiddleware"
Expand All @@ -27,9 +28,16 @@ class OperationInputBodyMiddleware(
operationStackName: String,
) {
val inputShapeName = MiddlewareShapeUtils.inputSymbol(symbolProvider, model, op).name
val hasHttpBody = MiddlewareShapeUtils.hasHttpBody(model, op)
if (hasHttpBody || shouldRender) {
writer.write("$operationStackName.${middlewareStep.stringValue()}.intercept(position: ${position.stringValue()}, middleware: ${inputShapeName}BodyMiddleware())")
val outputShapeName = MiddlewareShapeUtils.outputSymbol(symbolProvider, model, op).name
val errorShapeName = MiddlewareShapeUtils.outputErrorSymbolName(op)
if (alwaysSendBody) {
writer.write("$operationStackName.${middlewareStep.stringValue()}.intercept(position: ${position.stringValue()}, middleware: \$N<$inputShapeName, $outputShapeName, $errorShapeName>(alwaysSendBody: true))", ClientRuntimeTypes.Middleware.SerializableBodyMiddleware)
} else if (MiddlewareShapeUtils.hasHttpBody(model, op)) {
if (MiddlewareShapeUtils.bodyIsHttpPayload(model, op)) {
writer.write("$operationStackName.${middlewareStep.stringValue()}.intercept(position: ${position.stringValue()}, middleware: ${inputShapeName}BodyMiddleware())")
} else {
writer.write("$operationStackName.${middlewareStep.stringValue()}.intercept(position: ${position.stringValue()}, middleware: \$N<$inputShapeName, $outputShapeName, $errorShapeName>())", ClientRuntimeTypes.Middleware.SerializableBodyMiddleware)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import software.amazon.smithy.swift.codegen.middleware.MiddlewareStep

class OperationInputHeadersMiddleware(
val model: Model,
val symbolProvider: SymbolProvider,
val symbolProvider: SymbolProvider
) : MiddlewareRenderable {

override val name = "OperationInputHeadersMiddleware"
Expand All @@ -26,6 +26,9 @@ class OperationInputHeadersMiddleware(
operationStackName: String,
) {
val inputShapeName = MiddlewareShapeUtils.inputSymbol(symbolProvider, model, op).name
writer.write("$operationStackName.${middlewareStep.stringValue()}.intercept(position: ${position.stringValue()}, middleware: ${inputShapeName}HeadersMiddleware())")
val hasHeaders = MiddlewareShapeUtils.hasHttpHeaders(model, op)
if (hasHeaders) {
writer.write("$operationStackName.${middlewareStep.stringValue()}.intercept(position: ${position.stringValue()}, middleware: ${inputShapeName}HeadersMiddleware())")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ class OperationInputQueryItemMiddleware(
operationStackName: String,
) {
val inputShapeName = MiddlewareShapeUtils.inputSymbol(symbolProvider, model, op).name
writer.write("$operationStackName.${middlewareStep.stringValue()}.intercept(position: ${position.stringValue()}, middleware: ${inputShapeName}QueryItemMiddleware())")
val hasQueryItems = MiddlewareShapeUtils.hasQueryItems(model, op)
if (hasQueryItems) {
writer.write("$operationStackName.${middlewareStep.stringValue()}.intercept(position: ${position.stringValue()}, middleware: ${inputShapeName}QueryItemMiddleware())")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,21 @@ package software.amazon.smithy.swift.codegen.integration.middlewares
import software.amazon.smithy.codegen.core.SymbolProvider
import software.amazon.smithy.model.Model
import software.amazon.smithy.model.shapes.OperationShape
import software.amazon.smithy.model.traits.EndpointTrait
import software.amazon.smithy.swift.codegen.ClientRuntimeTypes
import software.amazon.smithy.swift.codegen.SwiftWriter
import software.amazon.smithy.swift.codegen.integration.EndpointTraitConstructor
import software.amazon.smithy.swift.codegen.integration.middlewares.handlers.MiddlewareShapeUtils
import software.amazon.smithy.swift.codegen.middleware.MiddlewarePosition
import software.amazon.smithy.swift.codegen.middleware.MiddlewareRenderable
import software.amazon.smithy.swift.codegen.middleware.MiddlewareStep
import software.amazon.smithy.swift.codegen.model.getTrait

class OperationInputUrlHostMiddleware(
val model: Model,
val symbolProvider: SymbolProvider,
val inputParameters: String
val operation: OperationShape,
val requiresHost: Boolean = false
) : MiddlewareRenderable {

override val name = "OperationInputUrlHostMiddleware"
Expand All @@ -27,6 +32,16 @@ class OperationInputUrlHostMiddleware(
operationStackName: String
) {
val inputShapeName = MiddlewareShapeUtils.inputSymbol(symbolProvider, model, op).name
writer.write("$operationStackName.${middlewareStep.stringValue()}.intercept(position: ${position.stringValue()}, middleware: ${inputShapeName}URLHostMiddleware($inputParameters))")
val outputShapeName = MiddlewareShapeUtils.outputSymbol(symbolProvider, model, op).name
val errorShapeName = MiddlewareShapeUtils.outputErrorSymbolName(op)

var inputParameters = if (requiresHost) "host: hostOnly" else ""
operation.getTrait<EndpointTrait>()?.let {
val inputShape = model.expectShape(operation.input.get())
val hostPrefix = EndpointTraitConstructor(it, inputShape).construct()
inputParameters += if (requiresHost) ", " else ""
inputParameters += "hostPrefix: \"$hostPrefix\""
}
writer.write("$operationStackName.${middlewareStep.stringValue()}.intercept(position: ${position.stringValue()}, middleware: \$N<$inputShapeName, $outputShapeName, $errorShapeName>($inputParameters))", ClientRuntimeTypes.Middleware.URLHostMiddleware)
}
}
Loading