BottleRocketStudios / iOS-Hyperspace

An extremely lightweight wrapper around URLSession to make working with APIs a breeze.
Apache License 2.0
47 stars 17 forks source link

Build out PreparationStrategy functionality #171

Closed wmcginty closed 1 year ago

wmcginty commented 1 year ago

Adds a property on BackendService for an array of PreparationStrategy. These are executed in order just before every request is sent, allowing for just-in-time modifications to the request before send. They execute async, and can throw. Errors thrown from a PreparationStrategy are not recoverable using the existingRecoveryStrategy machinery and throw to the caller immediately (they do not hit the server). This is useful for applying a dynamic property to every request that isn't as simple as setting a common header.

For example

struct SignatureApplyingPreparationStrategy: PreparationStrategy {

    func prepare<R>(toExecute request: Request<R>) async throws -> Request<R> {
        return request.addingHeaders([.signature: .init(rawValue: applySignature(using: request.url, body: request.body))])
    }

    func applySignature(using url: URL, body: Data?) -> String {
        // ...
    }
}

let backendService = BackendService(preparationStrategies: SignatureApplyingPreparationStrategy())
try await backendService.execute(request: myRequest)

Whereas previously this signature would need to be applied to each request, the PreparationStrategy allows this logic to reside in one place, apply to all outgoing requests, but still be based on the properties of each individual request.

wmcginty commented 1 year ago

@rmirabelli Do you mind taking a look at this when you get a chance?

rmirabelli commented 1 year ago

Sorry I didn't have much to say, I think I looked at the preparation strategies more broadly a week or two ago.