Skip to content

Commit

Permalink
feat!: Use closures for processing HTTP response (#624)
Browse files Browse the repository at this point in the history
  • Loading branch information
jbelkins authored Nov 30, 2023
1 parent 34aecef commit af13f00
Show file tree
Hide file tree
Showing 55 changed files with 259 additions and 281 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@
// SPDX-License-Identifier: Apache-2.0
//

public struct IdempotencyTokenMiddleware<OperationStackInput,
OperationStackOutput: HttpResponseBinding,
OperationStackError: HttpResponseErrorBinding>: ClientRuntime.Middleware {
public struct IdempotencyTokenMiddleware<OperationStackInput, OperationStackOutput>: ClientRuntime.Middleware {
public let id: Swift.String = "IdempotencyTokenMiddleware"
private let keyPath: WritableKeyPath<OperationStackInput, String?>

Expand Down
9 changes: 6 additions & 3 deletions Sources/ClientRuntime/Middleware/NoopHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
// SPDX-License-Identifier: Apache-2.0
//

public struct NoopHandler<Output: HttpResponseBinding>: Handler {
public struct NoopHandler<OperationStackOutput>: Handler {
public init() {}

public func handle(context: HttpContext, input: SdkHttpRequest) async throws -> OperationOutput<Output> {
return OperationOutput<Output>(httpResponse: HttpResponse())
public func handle(
context: HttpContext,
input: SdkHttpRequest
) async throws -> OperationOutput<OperationStackOutput> {
return OperationOutput<OperationStackOutput>(httpResponse: HttpResponse())
}
}
16 changes: 6 additions & 10 deletions Sources/ClientRuntime/Middleware/OperationStack.swift
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0.

public struct OperationStack<OperationStackInput,
OperationStackOutput: HttpResponseBinding,
OperationStackError: HttpResponseErrorBinding> {
public struct OperationStack<OperationStackInput, OperationStackOutput> {

/// returns the unique id for the operation stack as middleware
public var id: String
Expand All @@ -15,14 +13,11 @@ public struct OperationStack<OperationStackInput,

public init(id: String) {
self.id = id
self.initializeStep = InitializeStep<OperationStackInput,
OperationStackOutput>(id: InitializeStepId)
self.serializeStep = SerializeStep<OperationStackInput,
OperationStackOutput>(id: SerializeStepId)
self.initializeStep = InitializeStep<OperationStackInput, OperationStackOutput>(id: InitializeStepId)
self.serializeStep = SerializeStep<OperationStackInput, OperationStackOutput>(id: SerializeStepId)
self.buildStep = BuildStep<OperationStackOutput>(id: BuildStepId)
self.finalizeStep = FinalizeStep<OperationStackOutput>(id: FinalizeStepId)
self.deserializeStep = DeserializeStep<OperationStackOutput>(id: DeserializeStepId)

}

/// This execute will execute the stack and use your next as the last closure in the chain
Expand Down Expand Up @@ -53,6 +48,7 @@ public struct OperationStack<OperationStackInput,
mutating public func presignedRequest<H: Handler>(
context: HttpContext,
input: OperationStackInput,
output: OperationStackOutput,
next: H
) async throws -> SdkHttpRequestBuilder? where
H.Input == SdkHttpRequest,
Expand All @@ -61,9 +57,9 @@ public struct OperationStack<OperationStackInput,
var builder: SdkHttpRequestBuilder?
self.finalizeStep.intercept(
position: .after,
middleware: PresignerShim<OperationStackOutput, OperationStackError>(handler: { buildInMiddleware in
middleware: PresignerShim<OperationStackOutput>(handler: { buildInMiddleware in
builder = buildInMiddleware
}))
}, output: output))
_ = try await handleMiddleware(context: context, input: input, next: next)
return builder
}
Expand Down
17 changes: 5 additions & 12 deletions Sources/ClientRuntime/Middleware/PresignerShimHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,20 @@

typealias PresignerShimHandler = (SdkHttpRequestBuilder) -> Void

struct PresignerShim<OperationStackOutput: HttpResponseBinding,
OperationStackError: HttpResponseErrorBinding>: Middleware {
struct PresignerShim<OperationStackOutput>: Middleware {
public let id: String = "PresignerShim"

private let handler: PresignerShimHandler
private let output: OperationStackOutput

init(handler: @escaping PresignerShimHandler) {
init(handler: @escaping PresignerShimHandler, output: OperationStackOutput) {
self.handler = handler
self.output = output
}

public typealias MInput = SdkHttpRequestBuilder
public typealias MOutput = OperationOutput<OperationStackOutput>
public typealias Context = HttpContext
public typealias MError = OperationStackError

public func handle<H>(context: HttpContext,
input: SdkHttpRequestBuilder,
Expand All @@ -31,13 +31,6 @@ struct PresignerShim<OperationStackOutput: HttpResponseBinding,
Self.MOutput == H.Output {
handler(input)
let httpResponse = HttpResponse(body: .none, statusCode: .ok)
do {
let output: OperationStackOutput? = try await OperationStackOutput(
httpResponse: httpResponse,
decoder: nil)
return .init(httpResponse: httpResponse, output: output)
} catch {
throw ClientError.unknownError("PresignerShimHandler: This code should not execute")
}
return .init(httpResponse: httpResponse, output: output)
}
}
13 changes: 8 additions & 5 deletions Sources/ClientRuntime/Middleware/RetryMiddleware.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
// SPDX-License-Identifier: Apache-2.0
//

public struct RetryMiddleware<Strategy: RetryStrategy, ErrorInfoProvider: RetryErrorInfoProvider,
Output: HttpResponseBinding, OutputError: HttpResponseErrorBinding>: Middleware {
public struct RetryMiddleware<Strategy: RetryStrategy,
ErrorInfoProvider: RetryErrorInfoProvider,
OperationStackOutput>: Middleware {

public typealias MInput = SdkHttpRequestBuilder
public typealias MOutput = OperationOutput<Output>
public typealias MOutput = OperationOutput<OperationStackOutput>
public typealias Context = HttpContext

public var id: String { "Retry" }
Expand All @@ -20,15 +21,17 @@ public struct RetryMiddleware<Strategy: RetryStrategy, ErrorInfoProvider: RetryE
}

public func handle<H>(context: Context, input: SdkHttpRequestBuilder, next: H) async throws ->
OperationOutput<Output> where H: Handler, MInput == H.Input, MOutput == H.Output, Context == H.Context {
OperationOutput<OperationStackOutput>
where H: Handler, MInput == H.Input, MOutput == H.Output, Context == H.Context {

let partitionID = try getPartitionID(context: context, input: input)
let token = try await strategy.acquireInitialRetryToken(tokenScope: partitionID)
return try await sendRequest(token: token, context: context, input: input, next: next)
}

private func sendRequest<H>(token: Strategy.Token, context: Context, input: MInput, next: H) async throws ->
OperationOutput<Output> where H: Handler, MInput == H.Input, MOutput == H.Output, Context == H.Context {
OperationOutput<OperationStackOutput>
where H: Handler, MInput == H.Input, MOutput == H.Output, Context == H.Context {

do {
let serviceResponse = try await next.handle(context: context, input: input)
Expand Down
14 changes: 7 additions & 7 deletions Sources/ClientRuntime/Middleware/Steps/BuildStep.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@
/// Takes Request, and returns result or error.
///
/// Receives result or error from Finalize step.
public typealias BuildStep<O: HttpResponseBinding> = MiddlewareStep<HttpContext,
SdkHttpRequestBuilder,
OperationOutput<O>>
public typealias BuildStep<OperationStackOutput> = MiddlewareStep<HttpContext,
SdkHttpRequestBuilder,
OperationOutput<OperationStackOutput>>

public let BuildStepId = "Build"

public struct BuildStepHandler<OperationStackOutput: HttpResponseBinding,
H: Handler>: Handler where H.Context == HttpContext,
H.Input == SdkHttpRequestBuilder,
H.Output == OperationOutput<OperationStackOutput> {
public struct BuildStepHandler<OperationStackOutput, H: Handler>: Handler
where H.Context == HttpContext,
H.Input == SdkHttpRequestBuilder,
H.Output == OperationOutput<OperationStackOutput> {

public typealias Input = SdkHttpRequestBuilder

Expand Down
16 changes: 8 additions & 8 deletions Sources/ClientRuntime/Middleware/Steps/DeserializeStep.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@
/// Takes Request, and returns result or error.
///
/// Receives raw response, or error from underlying handler.
public typealias DeserializeStep<O: HttpResponseBinding> = MiddlewareStep<HttpContext,
SdkHttpRequest,
OperationOutput<O>>
public typealias DeserializeStep<OperationStackOutput> = MiddlewareStep<HttpContext,
SdkHttpRequest,
OperationOutput<OperationStackOutput>>

public let DeserializeStepId = "Deserialize"

public struct DeserializeStepHandler<OperationStackOutput: HttpResponseBinding,
H: Handler>: Handler where H.Context == HttpContext,
H.Input == SdkHttpRequest,
H.Output == OperationOutput<OperationStackOutput> {
public struct DeserializeStepHandler<OperationStackOutput, H: Handler>: Handler

Check warning on line 19 in Sources/ClientRuntime/Middleware/Steps/DeserializeStep.swift

View workflow job for this annotation

GitHub Actions / swiftlint

Lines should not have trailing whitespace (trailing_whitespace)
where H.Context == HttpContext,
H.Input == SdkHttpRequest,
H.Output == OperationOutput<OperationStackOutput> {

public typealias Input = SdkHttpRequest

Expand All @@ -36,7 +36,7 @@ public struct DeserializeStepHandler<OperationStackOutput: HttpResponseBinding,
}
}

public struct OperationOutput<Output: HttpResponseBinding> {
public struct OperationOutput<Output> {
public var httpResponse: HttpResponse
public var output: Output?

Expand Down
14 changes: 7 additions & 7 deletions Sources/ClientRuntime/Middleware/Steps/FinalizeStep.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@
// Takes Request, and returns result or error.
//
// Receives result or error from Deserialize step.
public typealias FinalizeStep<O: HttpResponseBinding> = MiddlewareStep<HttpContext,
SdkHttpRequestBuilder,
OperationOutput<O>>
public typealias FinalizeStep<OperationStackOutput> = MiddlewareStep<HttpContext,
SdkHttpRequestBuilder,
OperationOutput<OperationStackOutput>>

public let FinalizeStepId = "Finalize"

public struct FinalizeStepHandler<OperationStackOutput: HttpResponseBinding,
H: Handler>: Handler where H.Context == HttpContext,
H.Input == SdkHttpRequest,
H.Output == OperationOutput<OperationStackOutput> {
public struct FinalizeStepHandler<OperationStackOutput, H: Handler>: Handler
where H.Context == HttpContext,
H.Input == SdkHttpRequest,
H.Output == OperationOutput<OperationStackOutput> {

public typealias Input = SdkHttpRequestBuilder

Expand Down
15 changes: 6 additions & 9 deletions Sources/ClientRuntime/Middleware/Steps/InitializeStep.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,15 @@
/// Takes Input Parameters, and returns result or error.
///
/// Receives result or error from Serialize step.
public typealias InitializeStep<I,
O: HttpResponseBinding> = MiddlewareStep<HttpContext,
I,
OperationOutput<O>>
public typealias InitializeStep<OperationStackInput, OperationStackOutput> =
MiddlewareStep<HttpContext, OperationStackInput, OperationOutput<OperationStackOutput>>

public let InitializeStepId = "Initialize"

public struct InitializeStepHandler<OperationStackInput,
OperationStackOutput: HttpResponseBinding,
H: Handler>: Handler where H.Context == HttpContext,
H.Input == SerializeStepInput<OperationStackInput>,
H.Output == OperationOutput<OperationStackOutput> {
public struct InitializeStepHandler<OperationStackInput, OperationStackOutput, H: Handler>: Handler
where H.Context == HttpContext,
H.Input == SerializeStepInput<OperationStackInput>,
H.Output == OperationOutput<OperationStackOutput> {

public typealias Input = OperationStackInput

Expand Down
15 changes: 6 additions & 9 deletions Sources/ClientRuntime/Middleware/Steps/SerializeStep.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,15 @@
/// Converts Input Parameters into a Request, and returns the result or error.
///
/// Receives result or error from Build step.
public typealias SerializeStep<I,
O: HttpResponseBinding> = MiddlewareStep<HttpContext,
SerializeStepInput<I>,
OperationOutput<O>>
public typealias SerializeStep<OperationStackInput, OperationStackOutput> =
MiddlewareStep<HttpContext, SerializeStepInput<OperationStackInput>, OperationOutput<OperationStackOutput>>

public let SerializeStepId = "Serialize"

public struct SerializeStepHandler<OperationStackInput,
OperationStackOutput: HttpResponseBinding,
H: Handler>: Handler where H.Context == HttpContext,
H.Input == SdkHttpRequestBuilder,
H.Output == OperationOutput<OperationStackOutput> {
public struct SerializeStepHandler<OperationStackInput, OperationStackOutput, H: Handler>: Handler
where H.Context == HttpContext,
H.Input == SdkHttpRequestBuilder,
H.Output == OperationOutput<OperationStackOutput> {

public typealias Input = SerializeStepInput<OperationStackInput>

Expand Down
16 changes: 16 additions & 0 deletions Sources/ClientRuntime/Networking/Http/HTTPResponseClosure.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

public typealias HTTPResponseClosure<OperationStackOutput> = (HttpResponse) async throws -> OperationStackOutput

public func responseClosure<OperationStackOutput: HttpResponseBinding, Decoder: ResponseDecoder>(
decoder: Decoder
) -> HTTPResponseClosure<OperationStackOutput> {
return { response in
try await OperationStackOutput(httpResponse: response, decoder: decoder)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

public typealias HTTPResponseErrorClosure = (HttpResponse) async throws -> Error

public func responseErrorClosure<OperationErrorBinding: HttpResponseErrorBinding, Decoder: ResponseDecoder>(
_ errorBinding: OperationErrorBinding.Type,
decoder: Decoder
) -> HTTPResponseErrorClosure {
return { response in
try await OperationErrorBinding.makeError(httpResponse: response, decoder: decoder)
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0.

public struct ContentLengthMiddleware<OperationStackOutput: HttpResponseBinding>: Middleware {
public struct ContentLengthMiddleware<OperationStackOutput>: Middleware {
public let id: String = "ContentLength"

private let contentLengthHeaderName = "Content-Length"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import AwsCommonRuntimeKit

public struct ContentMD5Middleware<OperationStackOutput: HttpResponseBinding>: Middleware {
public struct ContentMD5Middleware<OperationStackOutput>: Middleware {
public let id: String = "ContentMD5"

private let contentMD5HeaderName = "Content-MD5"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0.

public struct ContentTypeMiddleware<OperationStackInput,
OperationStackOutput: HttpResponseBinding>: Middleware {
public struct ContentTypeMiddleware<OperationStackInput, OperationStackOutput>: Middleware {

public let id: String = "ContentType"

Expand Down
Loading

0 comments on commit af13f00

Please sign in to comment.