swift-server / swift-server/async-http-client

RFC: design suggestion: Make this a "3-tier library"

Open
#392 11 comments 4 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Swift
Stars
1.1k
Forks
156
PR merge metrics
No merged PRs in 30d

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 the TLSContext, 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

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading the current HTTPClient entry point and how it owns TLSContext, the connection pool, the event loop group, and per-request configuration. Compare those responsibilities with the proposed three tiers; done would require an agreed design for lifecycle, configuration overrides, and middleware, not just a localized edit.

Written by the indexing model from the issue text.

Assessment

Tech stack
swift
Domain
api, backend-api-design
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.