ComposableRequest
public struct ComposableRequest<RequestBody, ResponseBody, ResponseError> : Requestable where ResponseError : Error
A ComposableRequest
is a generic type used to execute HTTP requests without needing to create request-specific Requestable
types.
Basic usage might look like this:
cancellable = ComposableRequest<AnyJSON, AnyJSON, HTTPError>()
.path("/users")
.method(.post)
.headers([.contentType: .contentType(.json)])
.body(
[
"name": "morpheus",
"job": "leader"
]
)
.send(on: "https://reqres.in/api")
.sink { result in
// handle completion
} receiveValue: { response in
// handle response
}
You can specialize a ComposableRequest
with body types, as well as an error model of your choosing.
If you use body types String
, Data
, Codable
, RequestParameters
or AnyJSON
, default encoder and decoders are provided for you.
If you use an error type HTTPError
, a response validator is used for you.
If you provide your own error model, rember to provide a validator, as the default validator automatically allows all responses to continue
-
Create a
ComposableRequest
Declaration
Swift
public init()
-
Set the request path
let request = ComposableRequest<Any, Any, Error>() .path("/posts/create")
Declaration
Swift
public func path(_ path: String) -> ComposableRequest<RequestBody, ResponseBody, ResponseError>
Parameters
path
The path
Return Value
The request
-
Set the request path
let request = ComposableRequest<Any, Any, Error>() .path { // ... logic to determine the request path ... return path }
Declaration
Swift
public func path(_ pathBuilder: @escaping () -> String) -> ComposableRequest<RequestBody, ResponseBody, ResponseError>
Parameters
pathBuilder
The closure that builds the request path
Return Value
The request
-
Add a URL query
let request = ComposableRequest<Any, Any, Error>() .query(URLQueryItem(name: "key", value: "value"))
Declaration
Swift
public func query(_ query: URLQueryItem) -> ComposableRequest<RequestBody, ResponseBody, ResponseError>
Parameters
query
The query parameter
Return Value
The request
-
Add a URL query
let request = ComposableRequest<Any, Any, Error>() .query { // ... logic to determine the request query ... return URLQueryItem(name: "key", value: "value") }
Declaration
Swift
public func query(_ queryBuilder: @escaping () -> URLQueryItem) -> ComposableRequest<RequestBody, ResponseBody, ResponseError>
Parameters
queryBuilder
The closure that returns the URL query
Return Value
The request
-
Add URL queries
let request = ComposableRequest<Any, Any, Error>() .query(URLQueryItem(name: "key1", value: "value1"), URLQueryItem(name: "key2", value: "value2"))
Declaration
Swift
public func query(_ queries: URLQueryItem...) -> ComposableRequest<RequestBody, ResponseBody, ResponseError>
Parameters
queries
Query items
Return Value
The request
-
Replace the exsting URL queries with new ones
let request = ComposableRequest<Any, Any, Error>() .queries([URLQueryItem(name: "key1", value: "value1") URLQueryItem(name: "key2", value: "value2")])
Declaration
Swift
public func queries(_ query: [URLQueryItem]) -> ComposableRequest<RequestBody, ResponseBody, ResponseError>
Parameters
queries
The queries
Return Value
The request
-
Replace the existing URL queries with new ones
let request = ComposableRequest<Any, Any, Error>() .queries { // ... logic to determine the request queries ... return [URLQueryItem(name: "key1", value: "value1") URLQueryItem(name: "key2", value: "value2")] }
Declaration
Swift
public func queries(_ queryBuilder: @escaping () -> [URLQueryItem]) -> ComposableRequest<RequestBody, ResponseBody, ResponseError>
Parameters
queryBuilder
The closure that builds the queries
Return Value
The request
-
Set the HTTP method
let request = ComposableRequest<Any, Any, Error>() .method(.post)
Declaration
Swift
public func method(_ method: RequestMethod) -> ComposableRequest<RequestBody, ResponseBody, ResponseError>
Parameters
method
The method to use
Return Value
The request
-
Set the HTTP method
let request = ComposableRequest<Any, Any, Error>() .method { ... logic to determine the request method ... return .post }
Declaration
Swift
public func method(_ methodBuilder: @escaping () -> RequestMethod) -> ComposableRequest<RequestBody, ResponseBody, ResponseError>
Parameters
methodBuilder
Closure that builds the request method
Return Value
The request
-
Add a header
let request = ComposableRequest<Any, Any, Error>() .header(key: "User-Agent", value: "MyUserAgentValue")
Declaration
Swift
public func header(key: RequestHeaders.Key, value: RequestHeaders.Value?) -> ComposableRequest<RequestBody, ResponseBody, ResponseError>
Parameters
key
The header field
value
The header value
Return Value
The request
-
Add a header
let request = ComposableRequest<Any, Any, Error>() .header { /// ... logic to determine header ... return (key: "User-Agent", value: "MyUserAgentValue") }
Declaration
Swift
public func header(_ headerBuilder: @escaping () -> (RequestHeaders.Key, RequestHeaders.Value?)) -> ComposableRequest<RequestBody, ResponseBody, ResponseError>
Parameters
headerBuilder
The closure that builds the header
Return Value
The request
-
Add headers
let request = ComposableRequest<Any, Any, Error>() .headers(pair1, pair2, pair3)
Declaration
Swift
public func headers(_ pairs: (key: RequestHeaders.Key, value: RequestHeaders.Value)...) -> ComposableRequest<RequestBody, ResponseBody, ResponseError>
Parameters
pairs
The pairs of headers to add
Return Value
The request
-
Add headers
let request = ComposableRequest<Any, Any, Error>() .headers([pair1, pair2, pair3])
Declaration
Swift
public func headers(_ pairs: [(key: RequestHeaders.Key, value: RequestHeaders.Value)]) -> ComposableRequest<RequestBody, ResponseBody, ResponseError>
Parameters
pairs
The pairs of headers to add
Return Value
The request
-
Replace the existing headers with new ones
let request = ComposableRequest<Any, Any, Error>() .headers(["User-Agent" : "MyAgent", "ContentType": "application/json"])
Declaration
Swift
public func headers(_ headers: RequestHeaders) -> ComposableRequest<RequestBody, ResponseBody, ResponseError>
Parameters
headers
The new headers
Return Value
The request
-
Replace the existing headers with new ones
let request = ComposableRequest<Any, Any, Error>() .headers { /// ... logic to determine header ... return ["User-Agent" : "MyAgent", "ContentType": "application/json"] }
Declaration
Swift
public func headers(_ headersBuilder: @escaping () -> RequestHeaders) -> ComposableRequest<RequestBody, ResponseBody, ResponseError>
Parameters
headersBuilder
The closure that builds the headers
Return Value
The request
-
Set the request body
let request = ComposableRequest<Any, Any, Error>() .body(myBody)
Declaration
Swift
public func body(_ body: RequestBody?) -> ComposableRequest<RequestBody, ResponseBody, ResponseError>
Parameters
body
The body
Return Value
The request
-
Set the request body
let request = ComposableRequest<Any, Any, Error>() .body { // ... logic to determine body ... return myBody }
Declaration
Swift
public func body(_ bodyBuilder: @escaping () -> RequestBody?) -> ComposableRequest<RequestBody, ResponseBody, ResponseError>
Parameters
bodyBuilder
The closure that builds the body
Return Value
The request
-
Set the request authentication
let request = ComposableRequest<Any, Any, Error>() .authentication(.token(.bearer, "myToken"))
Declaration
Swift
public func authenticate(with authentication: RequestAuthentication?) -> ComposableRequest<RequestBody, ResponseBody, ResponseError>
Parameters
authentication
The authentication
Return Value
The request
-
Set the request authentication
let request = ComposableRequest<Any, Any, Error>() .authentication { /// ... logic to determine authentication ... return .token(.bearer, "myToken")) }
Declaration
Swift
public func authenticate(with authenticationBuilder: @escaping () -> RequestAuthentication?) -> ComposableRequest<RequestBody, ResponseBody, ResponseError>
Parameters
authenticationBuilder
The closure that builds the authentication
Return Value
The request
-
Set the request authentication using basic username and password credentials
let request = ComposableRequest<Any, Any, Error> .authentication(withUsername: "myUserName", password: "myPassword")
Declaration
Swift
public func authenticate(withUsername username: String, password: String) -> ComposableRequest<RequestBody, ResponseBody, ResponseError>
Parameters
username
Username
password
Password
Return Value
The request
-
Set the request authentication using an authorization token
let request = ComposableRequest<Any, Any, Error> .authentication(withToken: "myToken", type: .bearer)
Declaration
Swift
public func authenticate(withToken token: String, type: RequestAuthentication.TokenType) -> ComposableRequest<RequestBody, ResponseBody, ResponseError>
Parameters
token
The token
type
The type of token
Return Value
the request
-
Add a fallback response to the request
Declaration
Swift
public func fallbackResponse(_ fallbackResponse: RequestResponse<ResponseBody>?) -> ComposableRequest<RequestBody, ResponseBody, ResponseError>
Parameters
fallbackResponse
The response to use if the request fails
Return Value
The request
-
Add a fallback response to the request
Declaration
Swift
public func fallbackResponse(_ fallbackResponseBuilder: @escaping () -> RequestResponse<ResponseBody>?) -> ComposableRequest<RequestBody, ResponseBody, ResponseError>
Parameters
fallbackResponse
Closure that builds the fallback response, used if the request fails
Return Value
The request
-
Add a request body encoder
Declaration
Swift
public func encodeBody(with handler: @escaping (RequestBody?) throws -> Data?) -> ComposableRequest<RequestBody, ResponseBody, ResponseError>
Parameters
handler
Closure used to transform
RequestBody
intoData
Return Value
The request
-
Add a request body encoder
Declaration
Swift
public func encodeBody(with encoder: BodyEncoder<RequestBody>) -> ComposableRequest<RequestBody, ResponseBody, ResponseError>
Parameters
encoder
Encoder used to handle request
Return Value
The request
-
Add a response body decoder
Declaration
Swift
public func decodeBody(with handler: @escaping (Data?) throws -> ResponseBody?) -> ComposableRequest<RequestBody, ResponseBody, ResponseError>
Parameters
handler
Closure used to transform
ResponseBody
intoData
Return Value
The request
-
Add a response body decoder
Declaration
Swift
public func decodeBody(with decoder: BodyDecoder<ResponseBody>) -> ComposableRequest<RequestBody, ResponseBody, ResponseError>
Parameters
decoder
Decoder used to handle response
Return Value
The request
-
Add a response validator
Declaration
Swift
public func validateResponse(with handler: @escaping (Response) -> Result<Response, ResponseError>) -> ComposableRequest<RequestBody, ResponseBody, ResponseError>
Parameters
handler
Closure used to validate a
Response
Return Value
The request
-
Add a response validator
Declaration
Swift
public func validateResponse(with responseValidator: ResponseValidator<ResponseBody, ResponseError>) -> ComposableRequest<RequestBody, ResponseBody, ResponseError>
Parameters
responseValidator
Response validator
Return Value
The request
-
Add a timeout interval
Declaration
Swift
public func timeoutInterval(_ interval: TimeInterval) -> ComposableRequest<RequestBody, ResponseBody, ResponseError>
Parameters
interval
The interval for requests to timeout
Return Value
The request
-
Add a timeout interval
Declaration
Swift
public func timeoutInterval(_ intervalBuilder: @escaping () -> TimeInterval) -> ComposableRequest<RequestBody, ResponseBody, ResponseError>
Parameters
intervalBuilder
Closure to build the timeout interval
Return Value
The request
-
Send this request on the main thread
Declaration
Swift
public func send(on host: String, retries: Int = 0, sla: TimeInterval = 120) -> AnyPublisher<Response, Failure>
Parameters
host
The host
retries
The number of retries
sla
The SLA to use before timing out
Return Value
A publisher to observe request responses
-
Send this request
Declaration
Swift
public func send<S>(on host: String, retries: Int = 0, sla: S.SchedulerTimeType.Stride = .seconds(120), using scheduler: S) -> AnyPublisher<Response, Failure> where S: Scheduler
Parameters
host
The host
retries
The number of retries
sla
The SLA to use before timing out
scheduler
The scheduler to use
Return Value
A publisher to observe request responses
-
Declaration
Swift
public var path: String { get }
-
Declaration
Swift
public var query: [URLQueryItem] { get }
-
Declaration
Swift
public var method: RequestMethod { get }
-
Declaration
Swift
public var headers: RequestHeaders { get }
-
Declaration
Swift
public var body: RequestBody? { get }
-
Undocumented
Declaration
Swift
public var authentication: RequestAuthentication? { get }
-
Declaration
Swift
public var fallbackResponse: RequestResponse<ResponseBody>? { get }
-
Declaration
Swift
public var requestEncoder: BodyEncoder<RequestBody> { get }
-
Declaration
Swift
public var responseDecoder: BodyDecoder<ResponseBody> { get }
-
Declaration
Swift
public var responseValidator: ResponseValidator<ResponseBody, ResponseError> { get }
-
Declaration
Swift
public var timeoutInterval: TimeInterval { get }