RequestManager

open class RequestManager

Introduction

An object used to execute Requestable(s)

Basic usage might look like this:

struct MyRequest: Requestable {
    ...
}

let manager = RequestManager(host: "https://api.myapp.com")
let request = MyRequest()
let cancellable = manager.makeRequest(request,
                                      retries: 3,
                                      sla: .seconds(120),
                                      on: DispathQueue.main)
    .removeErrors()
    .map(\.body)
    .sink { responseBody in
        ...
    }

Publisher

The publisher created by the makeRequest methods return a RequestResponse and a RequestError. See the documentation on both of these generic types for more information.

Request Lifecycle & Error Handling

The request lifecycle creates many different points of failure, and provides users with a robust error model to determin what went wrong and where

  1. The request is created. Possible failures inlcude an invalid URL, or a failure to encode the RequestBody, if one is present
  2. The request is excecuted. Possible failures include a broken network connection, a missing host, or a timeout.
  3. The request is parsed. The only possible failure here would be an attempt to decode the response data
  4. The request is validated. The provided ResponseValidator examines the response’s headers, status code, and body and choose to manipulate it or throw and error. See the “Validation step below for more information.

When the manager encounters any of the errors describer above, you can choose to retry to request. The number of retries is specified as a paramater in the makeRequest<T, S>(_:retries:sla:on:fallback:) method. You can also specify an SLA by which all retries must complete, and an optional fallback response to use. The request object itself can also contain a fallback response.

Additional Headers

In addition to the headers specified in the Requestable, you can have the manager inject its own headers on every request it makes. This can be useful for handling things like authentication.

let manager = RequestManager(host: "https://www.apple.com")
manager.additionalHeaders = [.authorization, .authorization(username: "myusername", password: "mypassword"]
// these headers will be injected into every request

Default Headers

RequestManager automatically injects User-Agent, Accept-Encoding, and Accept-Language headers into every request it makes by default. You can disable this behavior by setting the shouldInjectDefaultHeaders property to false

Logging

RequestManager support logging via Apple Unified Logging To enable this, use one of the initializers that accept a log subsystem or an OSLog instance

Initializers

  • Create a RequestManager

    Declaration

    Swift

    public convenience init(host: String)

    Parameters

    host

    The host to send requests

  • Create a RequestManager using the default log

    Declaration

    Swift

    public convenience init(host: String, subsystem: String)

    Parameters

    host

    The host to send requests

    subsystem

    The subsystem to send logs

  • Create a RequestManager using a custom log

    Declaration

    Swift

    public convenience init(host: String, log: OSLog)

    Parameters

    host

    The host to send requests

    log

    The log

API

  • The host

    Declaration

    Swift

    public let host: String
  • log

    The log to use

    Declaration

    Swift

    public let log: OSLog?
  • Headers to add to every request

    Declaration

    Swift

    open var additionalHeaders: RequestHeaders
  • Undocumented

    Declaration

    Swift

    open var requestAuthentication: RequestAuthentication?
  • Whether or not to inject Ombi’s default headers

    Declaration

    Swift

    open var shouldInjectDefaultHeaders: Bool
  • Make a request

    Declaration

    Swift

    public final func makeRequest<T, S>(_ requestable: T,
                                        authentication: RequestAuthentication? = nil,
                                        retries: Int = 0,
                                        sla: S.SchedulerTimeType.Stride = .seconds(180.0),
                                        on scheduler: S,
                                        fallback: T.Response? = nil) -> AnyPublisher<T.Response, T.Failure> where T: Requestable, S: Scheduler

    Parameters

    requestable

    The Requestable to request

    retries

    The number of retries

    sla

    The SLA execute all retries before timing out

    scheduler

    The scheduler to use

    Return Value

    A Publisher to observe request responses or errors

  • Make a request

    Declaration

    Swift

    public final func makeRequest<T>(_ requestable: T,
                                     authentication: RequestAuthentication? = nil,
                                     retries: Int = 0,
                                     sla: TimeInterval = 180.0,
                                     fallback: T.Response? = nil) -> AnyPublisher<T.Response, T.Failure> where T: Requestable

    Parameters

    requestable

    The Requestable to request

    retries

    The number of retries

    sla

    The SLA to use before timing out

    Return Value

    A Publisher to observe request responses or errors