SmokeHTTP is a specialization of the generic HTTP client provided by async-http-client, providing the common functionality required to abstract service operations from the underlying HTTP protocol. This library is primarily used by SmokeFramework and SmokeAWS.
This library provides a number of features on top of those provided by async-http-client:
- The
HTTPRequestInputProtocol
andHTTPResponseOutputProtocol
protocols provide a mechanism to deconstruct an input type into the different components of a HTTP request and construct an output type from the components of a HTTP response respectively. - Protocol-based strategies for determining the threading-model for asynchronous completion handling.
- Support for exponential backoff retries.
- Logging and emission of invocation metrics.
- An extension point for handing request-level tracing.
To use SmokeHTTPClient, a user can instantiate an HTTPOperationsClient
in the constructor of their specific client with instantiated delegates (HTTPClientDelegate
, HTTPClientInvocationDelegate
) that are used to define client-specific logic.
SmokeHTTP follows the same support policy as followed by SmokeAWS here.
SmokeHTTP uses the Swift Package Manager. To use the framework, add the following dependency to your Package.swift.
For swift-tools version 5.2 and greater:
dependencies: [
.package(url: "https://github.com/amzn/smoke-http.git", from: "2.0.0")
]
.target(name: ..., dependencies: [
...,
.product(name: "SmokeHTTPClient", package: "smoke-http"),
]),
For swift-tools version 5.1 and prior:
dependencies: [
.package(url: "https://github.com/amzn/smoke-http.git", from: "2.0.0")
]
.target(
name: ...,
dependencies: [..., "SmokeHTTPClient"]),
Construct a HTTPClient using the following code:
import SmokeHTTPClient
let httpOperationsClient = HTTPOperationsClient(endpointHostName: endpointHostName,
endpointPort: endpointPort,
contentType: contentType,
clientDelegate: clientDelegate,
connectionTimeoutSeconds: connectionTimeoutSeconds,
eventLoopProvider: = .createNew)
The inputs to this constructor are:
- endpointHostName: The hostname to contact for invocations made by this client. Doesn't include the scheme or port.
- For example
dynamodb.us-west-2.amazonaws.com
.
- endpointPort: The port to contact for invocations made by this client.
- For example
443
.
- contentType: The content type of the request body for invocations made by this client.
- For example
application/json
.
- clientDelegate: An instance of a type conforming to the
HTTPClientDelegate
protocol. - connectionTimeoutSeconds: The timeout in seconds for requests made by this client.
- eventLoopProvider: The provider of the event loop for this client. Defaults to creating a new event loop.
There are a number of variants of the execute call on the HTTPOperationsClient
. Below describes one variant but all are broadly similar-
try httpOperationsClient.executeAsyncRetriableWithOutput(
endpointOverride: nil,
endpointPath = endpointPath,
httpMethod: .GET,
input: InputType,
completion: completion,
asyncResponseInvocationStrategy: asyncResponseInvocationStrategy,
invocationContext: invocationContext,
retryConfiguration: retryConfiguration,
retryOnError: retryOnError)
The inputs to this function are:
- endpointOverride: Overrides the hostname used for this invocation. Default to nil to use the endpoint provided during the initialization of the client.
- endpointPath: The path to contact for this invocation.
- httpMethod: The HTTPMethod for this invocation.
- input: An instance of a type conforming to the
HTTPRequestInputProtocol
protocol. - completion: A closure of type
(Result<OutputType, HTTPClientError>) -> ()
used to handle the outcome of the invocation.OutputType
must be a type that conforms to theHTTPResponseOutputProtocol
protocol. - asyncResponseInvocationStrategy: An invocation strategy for executing the completion handler.
- GlobalDispatchQueueAsyncResponseInvocationStrategy is provided as the default, which will execute the completion handler on the Global Dispatch Queue.
- SameThreadAsyncResponseInvocationStrategy is also provided which will execute the completion handler on the SwiftNIO callback thread within the client's event loop.
- invocationContext: An instance of type
HTTPClientInvocationContext
. - retryConfiguration: An instance of type
HTTPClientRetryConfiguration
to indicate how the client should handle automatic retries on failure. - . retryOnError: A closure of type
(HTTPClientError) -> Bool
that can be used to determine if an automatic retry should occur when the request failures with the provided error.
The complete list of variants for the HTTPOperationsClient.execute*
functions are:
executeAsyncRetriableWithOutput
: Executes a HTTP request asynchronously with built-in support for automatic retries that produces an output.executeAsyncRetriableWithoutOutput
: Executes a HTTP request synchronously with built-in support for automatic retries that doesn't produce an output.executeAsyncWithoutOutput
: Executes a HTTP request asynchronously without built-in support for automatic retries that doesn't produce an output.executeAsyncWithOutput
: Executes a HTTP request asynchronously without built-in support for automatic retries that produces an output.executeSyncRetriableWithoutOutput
: Executes a HTTP request synchronously with built-in support for automatic retries that doesn't produce an output.executeSyncRetriableWithOutput
: Executes a HTTP request synchronously with built-in support for automatic retries that produces an output.executeSyncWithoutOutput
: Executes a HTTP request synchronously without built-in support for automatic retries that doesn't produce an output.executeSyncWithOutput
: Executes a HTTP request synchronously without built-in support for automatic retries that produces an output.
The HTTPClientDelegate
protocol provides a number extension points that can be used to customise a client.
Protocol function requirements:
getResponseError
: determines the client-specific error based on the HTTP response from the client.encodeInputAndQueryString
: determines the components to be used for the HTTP request based on the input to an invocation.decodeOutput
creates an instance of an output type based on the HTTP response from the client.getTLSConfiguration
: retrieves the TLS configuration to be used by the client.
The HTTPClientDelegate
protocol provides a number extension points that can be used to customise the invocation of a client.
Protocol property requirements:
specifyContentHeadersForZeroLengthBody
: If theContent-Length
andContent-Type
headers should be sent in the request even when there is no request body.
Protocol function requirements:
addClientSpecificHeaders
: determines any additional headers to be added to HTTP request.handleErrorResponses
: determines the client-specific error based on the HTTP response from the client. OverridesHTTPClientDelegate.getResponseError
if a non-nil error is returned.
The HTTPRequestInputProtocol
provides a mechanism used to transform an input into the different parts of a HTTP request. For an example of how this protocol is used to deconstruct an input type into a HTTP request see JSONAWSHttpClientDelegate.encodeInputAndQueryString().
Protocol property requirements:
queryEncodable
: Optionally, provides an instance of a type conforming toEncodable
that will be used to produce the query for the HTTP request.pathEncodable
: Optionally, provides an instance of a type conforming toEncodable
that will be used to provide any tokenized values for the path of the HTTP request.bodyEncodable
: Optionally, provides an instance of a type conforming toEncodable
that will be used to produce the body for the HTTP request.additionalHeadersEncodable
: Optionally, provides an instance of a type conforming toEncodable
that will be used to produce additional headers for the HTTP request.pathPostfix
: Optionally, provides a string that will be post-pended to the path template prior to having any tokens replaced by values frompathEncodable
.
The HTTPResponseOutputProtocol
provides a mechanism to construct an output type from the components of a HTTP response. For an example of how this is achieved see JSONAWSHttpClientDelegate.decodeOutput().
Protocol function requirements:
compose
: A function that acceptsbodyDecodableProvider
andheadersDecodableProvider
closures that can be used to construct parts of the expected output type from parts of the HTTP response.
The HTTPClientInvocationContext
type can be used to customise the invocation of a client.
The inputs to the HTTPClientInvocationContext
constructor are:
reporting
: An instance of a type conforming to theHTTPClientInvocationReporting
protocol.handlerDelegate
: An instance of a type conforming to theHTTPClientInvocationDelegate
protocol.
The HTTPClientInvocationReporting
protocol provides a number of extension points focused on the reporting of a client invocation-
Protocol property requirements:
logger
: The logger to use for statements related to the HTTP client invocation.internalRequestId
: the internal identity of the request that is making the invocation to the client.traceContext
: An instance of a type conforming to theInvocationTraceContext
protocol.successCounter
: Optionally, aMetrics.Counter
that will record successful invocations of the client.failure5XXCounter
: Optionally, aMetrics.Counter
that will record unsuccessful invocations of the client that return with a 5xx response code.failure4XXCounter
: Optionally, aMetrics.Counter
that will record unsuccessful invocations of the client that return with a 4xx response code.retryCountRecorder
: Optionally, aMetrics.Recorder
that will record the retry count for invocations of the client.latencyTimer
: Optionally, aMetrics.Recorder
that will record the latency of invocations from the client.
The InvocationTraceContext
provides an extension point for request-level tracing.
Protocol function requirements:
handleOutwardsRequestStart
: Provides the ability to handle an invocation of the client just prior to the request being sent, including the ability to modify the headers sent in the request.handleOutwardsRequestSuccess
: Provides the ability to handle a successful invocation just after the response has been received.handleOutwardsRequestFailure
: Provides the ability to handle a unsuccessful invocation just after the response has been received.
This library is licensed under the Apache 2.0 License.