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!: Use closures for processing HTTP response #624

Merged
merged 8 commits into from
Nov 30, 2023
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
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) {
Copy link
Contributor Author

@jbelkins jbelkins Nov 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the removal of the HttpResponseBinding protocol means that this middleware can no longer create an OperationStackOutput, one is passed into this middleware at creation.

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 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
Loading