[HTTP]ServerRequestAn inbound request: the parsed head plus the body as an [HTTP]Body — stream-backed while undrained, empty bytes-backed when the request has none, so handlers never nil-check. target is the raw request-target as sent (undecoded — percent decoding is the [Web] layer's job); version is the HTTP/1.x minor (0 | 1). (@params is an inert slot here: the [Web] router binds route params into it through the reopened params:/param: conveniences.)
The [Web] layer's request conveniences, layered onto the transport request by reopening — extension by <-- is the Quoin way to layer without wrappers.
The body as an [HTTP]Body — stream-backed until read; a request without one answers an empty body, never nil.
The body parsed as application/x-www-form-urlencoded ('+' means space).
Case-insensitive lookup of the first header named name, or nil.
Headers as a #(name value) pair list, order- and duplicate-preserving.
Internal: normalize the head fields — nil headers become #(), a nil body an empty bytes-backed one.
The body parsed as JSON; bad input throws a catchable ParseError.
The body's lowercased media type ('application/json'), or nil.
The request verb as sent (e.g. 'GET').
One route binding by name ('/users/:id' -> req.param:'id'), or nil.
Route bindings as a Map (set by the app's router before the handler runs).
Internal: bind the route params (the router calls this before the handler).
The request path: the raw target with any query string stripped. Segments stay percent-encoded — the router decodes per segment, so an encoded %2F can't split the path; params/query values arrive decoded.
The query string as a decoded Map ('+' stays literal), parsed on demand.
One decoded query value by name, or nil.
The raw request-target exactly as sent, query string included, undecoded.
Human rendering: verb and target.
The raw request-target as sent, query included, still percent-encoded (decoding is the [Web] layer's job — see path / query / params there).
The HTTP/1.x minor version: 0 or 1.