One Proxied Request, Fully Traced
1. A connection becomes a typed target
The listener accepts a socket and captures original destination, peer address, transport labels, and drain state. Inbound detection peeks at bytes under a timeout to distinguish TLS, HTTP, and opaque transport. The result enriches a target value used to instantiate the next stack.
2. NewService specializes the stack
Layers do not inspect global configuration on every request. NewService<T>
receives a target and constructs a concrete Service<Request> with cloned
parameters, policy receivers, metrics labels, caches, and inner services.
Param<T>
statically declares which configuration a target supplies.
3. HTTP middleware transforms and authorizes
The inbound stack normalizes URIs, attaches tracing/metrics, applies server policy and route policy, classifies responses, and selects local forwarding or gateway/outbound behavior. Each layer wraps the same readiness/call contract.
4. Outbound discovery becomes a service set
Logical destination and route policy select a cached per-target router. Controller or DNS updates feed endpoint add/remove changes. Each endpoint service encapsulates connect, TLS identity, protocol client, timeouts, and metrics.
5. Readiness chooses capacity before ownership transfer
A queue absorbs only configured backlog. The balancer polls endpoint readiness
and chooses an available endpoint using load. Service::call then owns the
request future. For HTTP/2, many request futures may share one connection; HTTP/1
has different connection concurrency.
6. Completion walks wrappers outward
The endpoint response returns through classification, retry, timeout, tracing, and metrics bodies. End-of-stream matters: a successful response head is not necessarily successful delivery if its body later fails.