Open
Description
At the moment, we have a pretty gnarly issue with AHC's API: Settings can either be supplied globally or per request. So if you want to set certain configuration for a certain component in your app (say TLS config, redirect config, ...) then you either have to specify it for every single request (tedious) or globally (expensive as you'll get a new connection pool, need to maintain lifecycle etc).
What I suggest here is making AHC a "3-tier library":
- tier 1: What is currently
HTTPClient
: the highly stateful, expensive, and lifecycle-managed object that owns theTLSContext
, the connection pool, and if not.shared
also the ELG - tier 2: (doesn't exist right now) A very lightweight (probably
struct
) and not lifecycle managed client object which is essentially a reference to the tier 1 object and a bag of configuration - tier 3: the individual requests
An API sketch could look like this:
// tier 1
let http = HTTPService(eventLoopGroupProvider: .shared(myELG)) // This is currently called `HTTPClient`
defer {
try! http.syncShutdown()
}
// tier 2 (creating this is ~free, doesn't need to be shut down)
let httpClient = http.client(tlsConfiguration: specialConfig, redirectConfig: ...)
// tier 3
let result = httpClient.get("https://...").wait()
Benefits
- Allows wider sharing of Tier 1 because it doesn't take configuration
- Makes the API nicer to use because we can supply configuration to Tier 2 so we don't need to pass it to every request
- Would allow Tier 2 to grow a "middleware" concept which would allow doing things like authenticating requests or controlling redirects etc without hard-wiring all that into the core HTTP client.
Important requirements per tier
Tier 1
- do not take any configuration apart from the ELG
Tier 2
- doesn't need lifecycle management
- holds bags of configuration
- ~free to create
Tier 3
- can override most(all?) of the configuration set in Tier 2
Metadata
Metadata
Assignees
Labels
No labels