# gizlang:http

HTTP/1.1 (RFC 9112) over any Stream of gizlang:system, so HTTPS is the same code over a stream secured by gizlang:tls. `serve` keeps its connections in a Ready set, without a task each, and answers what they send in a few worker tasks; `exchange` sends one request and reads its response, and a `Pool` keeps client connections alive to send more on them. Header names are kept in lower case.

```gizlang
import * as Http from "gizlang:http";
```

## Types

### `Header`

```gizlang
type Header = { name: string; value: string; }
```

One header: its name and value.

- `name`: `string`
- `value`: `string`

### `Request`

```gizlang
type Request = { method: string; path: string; headers: Vec<Header>; body: bytes; }
```

An HTTP request: method, path with its query, headers and body.

- `method`: `string`
- `path`: `string`
- `headers`: `Vec<gizlang_http.Header>`
- `body`: `bytes`

### `Response`

```gizlang
type Response = { status: i64; headers: Vec<Header>; body: bytes; }
```

An HTTP response: status, headers and body.

- `status`: `i64`
- `headers`: `Vec<gizlang_http.Header>`
- `body`: `bytes`

### `HttpError`

```gizlang
type HttpError = { status: i64; code: i64; message: string; }
```

status is the HTTP status a server answers with (400, 413, 431, 501), or 0
when the connection itself failed; code is then the IoError's.

- `status`: `i64`
- `code`: `i64`
- `message`: `string`

### `ExchangeHandler`

```gizlang
type ExchangeHandler = (exchange: mut Exchange) => Result<bool, HttpError>
```

A handler that writes its reply to the exchange itself. It returns whether the reply is complete.

### `ReplyPlan`

```gizlang
type ReplyPlan = | { kind: "buffered"; response: Response; } | { kind: "progressive"; render: ExchangeHandler; }
```

One reply contract for buffered handlers and progressive renderers. Ordinary
Response handlers retain static dispatch; a mixed handler may return Reply.
Progressive callbacks must finish the borrowed exchange before succeeding.

- `buffered`
- `progressive`

### `Reply`

```gizlang
interface Reply { plan(self: Self): ReplyPlan; }
```

A value that a handler may return: it says how to answer (`plan`).

- `plan`

### `Trace`

```gizlang
type Trace = { id: string; span: string; }
```

A W3C trace context (the traceparent header): the trace id (32 lowercase
hex digits) and the span id (16) of the caller's span, neither all zeros.

- `id`: `string`
- `span`: `string`

### `RequestHead`

```gizlang
type RequestHead = (request: Request) => Option<ExchangeHandler> effects { io, fail }
```

Select a streamed exchange from the request head, or use the buffered handler.

### `Exchange`

```gizlang
type Exchange
```

One request's exchange. On a multiplexed transport (`_mux`: HTTP/2 or HTTP/3) the same methods frame the reply as HEADERS and DATA.

- `request`: `gizlang_http.Request`

### `Incoming`

```gizlang
type Incoming
```

A response whose body is read as it arrives (an event stream, a long
download): `next` gives each piece the connection delivers, `event` each
server-sent event, `rest` all that is left, `whole` the response. `close`
ends the connection. Reading to the end leaves a one-shot connection open,
and gives a pooled connection back to its Pool.

- `status`: `i64`
- `headers`: `Vec<gizlang_http.Header>`
- `reason`: `string`

### `Event`

```gizlang
type Event = { name: string; data: string; }
```

A server-sent event (text/event-stream): its name ("message" when the event
names none) and its data lines joined by "\n".

- `name`: `string`
- `data`: `string`

### `Outgoing`

```gizlang
type Outgoing
```

A bounded request writer. The caller supplies the exact body length (UNKNOWN_LENGTH sends the body chunked) and
writes pieces; finish refuses truncation before reading the response.

Opaque: create and use it through this module's functions.

### `Feed`

```gizlang
type Feed
```

A request parser fed the bytes its caller reads (a JavaScript runtime's socket), with the rules of `serve`: the
same head and body parsing, one message after another. A response feed (responseFeed) parses responses as
`exchange` does, interim ones included.

Opaque: create and use it through this module's functions.

### `Parsed`

```gizlang
type Parsed = | { kind: "head"; request: Request; http10: bool; keep: bool; upgrade: bool; } | { kind: "status"; status: i64; reason: string; headers: Vec<Header>; http10: bool; keep: bool; upgrade: bool; } | { kind: "body"; data: bytes; } | { kind: "end"; } | { kind: "more"; } | { kind: "failed"; error: HttpError; }
```

What the fed bytes give next: a request head (keep: the connection stays open after its response; upgrade: the
request asks for another protocol or is CONNECT), a piece of its body, the end of the message, a need for more
bytes, or a parse error (then the feed stops).

- `head`
- `status`
- `body`
- `end`
- `more`
- `failed`

### `Origin`

```gizlang
type Origin = { secure: bool; host: string; port: i64; }
```

Where a pooled request goes: an origin (RFC 6454) is the scheme, the host
and the port. Connections are kept and reused only for the same origin.

- `secure`: `bool`
- `host`: `string`
- `port`: `i64`

### `Url`

```gizlang
type Url = { secure: bool; host: string; port: i64; target: string; }
```

An absolute http or https URL as a client uses it: whether it is secure,
the host, the port (the scheme's when none is written) and the request
target (path and query, "/" at least; a fragment is dropped).

- `secure`: `bool`
- `host`: `string`
- `port`: `i64`
- `target`: `string`

### `PoolOptions`

```gizlang
type PoolOptions = { perOrigin: i64; total: i64; idleMs: i64; }
```

A Pool's bounds: the idle connections kept for one origin and for all
origins, and how long one is kept idle (0 keeps none).

- `perOrigin`: `i64`
- `total`: `i64`
- `idleMs`: `i64`

### `Pool`

```gizlang
type Pool
```

HTTP/1.1 keep-alive connections (RFC 9112 9.3) that requests share, kept
per origin. A request takes an idle connection of its origin, or else
dials a new one; the response gives it back when its body is read to the
end. A connection is never given back after an error, after `close` of an
unfinished body, when either side sends `connection: close`, or when the
response has no framing (its body ends when the connection does). An
HTTPS connection keeps its TLS session, so a reused one does no new
handshake. A Pool belongs to the thread (World) that made it; the tasks of
that thread may share it.

- `options`: `gizlang_http.PoolOptions`

### `Asset`

```gizlang
type Asset = { path: string; contentType: string; body: bytes; }
```

An immutable content-addressed asset, shared by page shells and app hosts.

- `path`: `string`
- `contentType`: `string`
- `body`: `bytes`

### `PartLimits`

```gizlang
type PartLimits = { parts: i64; head: i64; field: i64; file: i64; total: i64; }
```

The bounds of a multipart/form-data body: the number of parts, the head bytes of one part, the bytes of
one field (a part without a filename), of one file, and of the whole body. Over a bound, the body is 413.

- `parts`: `i64`
- `head`: `i64`
- `field`: `i64`
- `file`: `i64`
- `total`: `i64`

### `Part`

```gizlang
type Part = { name: string; filename: Option<string>; contentType: string; }
```

The head of one part: its form field name, its filename when it is a file, and its media type
("text/plain" when the part names none).

- `name`: `string`
- `filename`: `_gizlang_sdk_core.Option<string>`
- `contentType`: `string`

### `PartEvent`

```gizlang
type PartEvent = | { kind: "start"; part: Part; } | { kind: "data"; data: bytes; } | { kind: "end"; }
```

What a multipart body gives in order: each part starts, gives its bytes in pieces, and ends.

- `start`
- `data`
- `end`

### `Multipart`

```gizlang
type Multipart
```

A multipart/form-data body (RFC 7578) read as it arrives: `push` takes the bytes in pieces of any size and
gives the events they complete. It keeps less than one delimiter of a part's bytes, or one part head.

Opaque: create and use it through this module's functions.

### `Files`

```gizlang
type Files = { dir: Dir; kept: Ref<Map<string, Kept>>; bytes: Ref<i64>; }
```

The files below `dir` that `fileReply` serves. They keep, for each file
served, its validators, its response headers and, up to MOST_KEPT_FILE bytes
(MOST_KEPT_BYTES in all), its body, as nginx's open_file_cache keeps
handles. A kept file is checked against the folder (one stat) at most once
in KEPT_VALID_MS. Make one for each serving thread (it holds a Ref).

- `dir`: `gizlang_system.Dir`
- `kept`: `Ref<_gizlang_sdk_collections.Map<string, gizlang_http.Kept>>`
- `bytes`: `Ref<i64>`

### `Kept`

```gizlang
type Kept = { size: i64; modified: i64; tag: string; headers: Vec<Header>; body: bytes; whole: bool; checked: i64; }
```

A file's validators and headers; its body when `whole`.

- `size`: `i64`
- `modified`: `i64`
- `tag`: `string`
- `headers`: `Vec<gizlang_http.Header>`
- `body`: `bytes`
- `whole`: `bool`
- `checked`: `i64`

### `Span`

```gizlang
type Span = { start: i64; end: i64; }
```

A byte range from START to END, END excluded.

- `start`: `i64`
- `end`: `i64`

### `ByteRange`

```gizlang
type ByteRange = | { kind: "valid"; span: Span; } | { kind: "malformed"; } | { kind: "unsatisfiable"; }
```

The parsed Range header: a valid span, a malformed header, or a range outside the file.

- `valid`
- `malformed`
- `unsatisfiable`

### `Balancer`

```gizlang
type Balancer
```

Requests shared by several upstreams in turn. An upstream that cannot be reached is skipped for `holdMs`, and an idempotent request (GET, HEAD, OPTIONS, PUT, DELETE) that failed on it goes to the next one; other methods are not sent twice, but go on when the connection was refused (nothing was sent). The standby upstreams (`standing`) are tried, in their order, only after the upstreams.

Opaque: create and use it through this module's functions.

### `Policy`

```gizlang
type Policy = { waitMs: i64; retries: i64; retryOn: Vec<i64>; replaceOn: Vec<i64>; fallback: Option<Origin>; }
```

How a balancer treats failures. `waitMs`: the longest wait for a response head (0: none). `retries`: more tries of an idempotent request
when an upstream answers with a status in `retryOn`. `replaceOn`: statuses (and an upstream that cannot be reached, as 502) whose answer
is replaced by the page `fallback` serves at "/", with the status kept.

- `waitMs`: `i64`
- `retries`: `i64`
- `retryOn`: `Vec<i64>`
- `replaceOn`: `Vec<i64>`
- `fallback`: `_gizlang_sdk_core.Option<gizlang_http.Origin>`

### `Relay`

```gizlang
type Relay = { extra: Vec<Header>; done: (status: i64, sent: i64) => void; }
```

What a relay adds to an answer and learns from it: `extra`, header fields put on it unless the upstream gave one of that name, and
`done`, called once when the answer has ended or failed with its status and the body bytes sent (101 with none for an upgrade).

- `extra`: `Vec<gizlang_http.Header>`
- `done`: `(status: i64, sent: i64) => void`

### `Params`

```gizlang
type Params = { names: Vec<string>; values: Vec<string>; }
```

One declaration owns dispatch and reverse URLs. Compile the declarations
once before serving; resolution never reparses a pattern. A literal beats
a single-segment `{name}`, which beats a final `*name`, independently of
registration order.

- `names`: `Vec<string>`
- `values`: `Vec<string>`

### `Route`

```gizlang
type Route<T> = { method: string; pattern: string; target: T; }
```

One route: the METHOD, the PATTERN (literals, `{name}` segments and an optional last `*name`) and the TARGET that it selects.

Opaque: create and use it through this module's functions.

### `Routed`

```gizlang
type Routed<T> = { target: T; params: Params; }
```

The result of a match: the target and the values of the pattern's names.

Opaque: create and use it through this module's functions.

### `Router`

```gizlang
type Router<T>
```

The compiled routes. Make it once with `router` before serving.

Opaque: create and use it through this module's functions.

### `Message`

```gizlang
type Message = { text: bool; data: bytes; }
```

One message: UTF-8 text, or binary data.

- `text`: `bool`
- `data`: `bytes`

### `WebSocket`

```gizlang
type WebSocket
```

An open WebSocket. receive gives each message; ping and close frames are answered here.

Opaque: create and use it through this module's functions.

### `SocketSession`

```gizlang
type SocketSession = (socket: mut WebSocket) => Result<bool, HttpError>
```

What runs on an opened server socket until it returns.

### `Mux`

```gizlang
type Mux = { pieces: Task.Channel<bytes>; consumed: (count: i64) => void; head: (status: i64, headers: Vec<Header>, length: i64, end: bool) => Result<bool, HttpError>; data: (data: bytes, end: bool) => Result<bool, HttpError>; trailers: (fields: Vec<Header>) => Result<bool, HttpError>; ended: Ref<bool>; }
```

The stream of an Exchange on a multiplexed transport: the request body pieces arrive on `pieces` (`consumed` returns their flow-control
credit), and the reply leaves as `head`, `data` and `trailers`; `ended` says the stream ended with the reply.

- `pieces`: `gizlang_task.Channel<bytes>`
- `consumed`: `(index: i64) => void`
- `head`: `(status: i64, headers: Vec<gizlang_http.Header>, length: i64, end: bool) => _gizlang_sdk_core.Result<bool, gizlang_http.HttpError>`
- `data`: `(data: bytes, end: bool) => _gizlang_sdk_core.Result<bool, gizlang_http.HttpError>`
- `trailers`: `(fields: Vec<gizlang_http.Header>) => _gizlang_sdk_core.Result<bool, gizlang_http.HttpError>`
- `ended`: `Ref<bool>`

### `Qpack`

```gizlang
type Qpack = { table: Vec<Header>; tree: Huffman; }
```

The QPACK static table with the Huffman tree, the state that qpackDecode and qpackBlock share (build it once).

- `table`: `Vec<gizlang_http.Header>`
- `tree`: `gizlang_http.Huffman`

### `H2Client`

```gizlang
type H2Client
```

An HTTP/2 connection as a client.

- `status`: `i64` — The reply's status, 0 until its head arrived.
- `headers`: `Vec<gizlang_http.Header>`
- `trailers`: `Vec<gizlang_http.Header>`

### `Limiter`

```gizlang
type Limiter
```

At most `limit` requests from one client (`clientOf`) within `windowMs`.

Opaque: create and use it through this module's functions.

### `Counted`

```gizlang
type Counted = { client: string; count: i64; first: i64; last: i64; }
```

What a store keeps of a client's requests in the window: how many, and the wall-clock time (ms) of the first and the last.

- `client`: `string`
- `count`: `i64`
- `first`: `i64`
- `last`: `i64`

## Functions

### `header`

```gizlang
function header(headers: Vec<Header>, name: string): Option<string>
```

The first value of a header, its name in any case.

Effects: fail.

### `traceOf`

```gizlang
function traceOf(headers: Vec<Header>): Option<Trace>
```

The valid version-00 traceparent among `headers`, else none.

Effects: fail.

### `traceparent`

```gizlang
function traceparent(t: Trace): string
```

The traceparent value of `t`, sampled.

Effects: fail.

### `text`

```gizlang
function text(status: i64, body: string): Response
```

A plain UTF-8 text response with STATUS and BODY.

Effects: fail.

### `serve`

```gizlang
function serve<F>(listener: Listener, handler: F): i64 throws IoError
```

Accept connections and answer each request with handler(request), until
accepting fails (as when the listener is closed) or the task is cancelled,
which closes the connections. A connection waits in a Ready set between
requests; a handler fault ends only the connection it was answering, and a
connection idle for IDLE_MS is closed.

### `serveStreamed`

```gizlang
function serveStreamed<F>(listener: Listener, handler: F, head: RequestHead): i64 throws IoError
```

serve, and head chooses a streamed exchange for a request from its head
(an upload, a long response); the requests it leaves go to handler.

### `serveReady`

```gizlang
function serveReady<F>(set: Ready, handler: F): i64 throws IoError
```

Answer the requests of the connections a Ready set reports, as serve does,
until the set stops (gizlang:tls's serve fills the set itself).

### `serveReadyStreamed`

```gizlang
function serveReadyStreamed<F>(set: Ready, handler: F, head: RequestHead): i64 throws IoError
```

serveReady with a streamed-exchange head, as serveStreamed.

### `dateField`

```gizlang
function dateField(name: string, ms: i64, second: Ref<i64>, line: Ref<bytes>): bytes
```

The Date field line NAME: <IMF-fixdate> CRLF for wall time MS, made at most once a second into LINE for the second in
SECOND: Web.serve's "date" and node:http's "Date" share this one cache rule.

Effects: fail, read, write.

### `chunkHead`

```gizlang
function chunkHead(out: mut bytes, size: i64): void
```

A chunk's size line (RFC 9112 7.1): SIZE in lowercase hex, then CRLF, appended to OUT.

Effects: fail.

### `open`

```gizlang
function open(stream: Stream, host: string, request: Request): Incoming throws HttpError
```

Send one request on a stream and read the response head; the body is then
read from the Incoming, which owns the stream. `host` is sent as the Host
header, and `connection: close` asks the server to end the connection.

Effects: fail, write, io.

### `outgoing`

```gizlang
function outgoing(stream: Stream, host: string, request: Request, size: i64): Outgoing throws HttpError
```

Writes the head of REQUEST to HOST on STREAM, for a body of SIZE bytes (UNKNOWN_LENGTH sends it chunked).

Effects: fail, io.

### `feed`

```gizlang
function feed(): Feed
```

A parser of HTTP/1.1 messages that takes the bytes as they arrive.

### `responseFeed`

```gizlang
function responseFeed(): Feed
```

A feed of responses: each head is a `status` (keep: the connection can carry another request; upgrade: 101).

### `exchange`

```gizlang
function exchange(stream: Stream, host: string, request: Request): Response throws HttpError
```

Send one request on a stream and read the whole response; the stream is
closed after it. `host` is sent as the Host header.

Effects: fail, read, write, console, io.

### `fetch`

```gizlang
function fetch(system: System, host: string, port: i64, request: Request): Response throws HttpError
```

A plain-HTTP request to host:port.

Effects: fail, read, write, console, io.

### `fetchUpTo`

```gizlang
function fetchUpTo(system: System, host: string, port: i64, request: Request, most: i64): Response throws HttpError
```

As `fetch`, for a response of up to `most` bytes (MOST_BODY holds for `fetch`).

Effects: fail, read, write, console, io.

### `url`

```gizlang
function url(text: string): Option<Url>
```

`text` as an http or https URL; none for another scheme, user info, an
empty host or a bad port.

Effects: fail.

### `poolDefaults`

```gizlang
function poolDefaults(): PoolOptions
```

The default pool options: POOL_PER_ORIGIN, POOL_TOTAL and POOL_IDLE_MS.

### `pool`

```gizlang
function pool(system: System, options: PoolOptions): Pool
```

A Pool of plain-HTTP connections; an https origin is refused (gizlang:tls's
`pool` secures them).

Effects: fail, write.

### `poolDialing`

```gizlang
function poolDialing(options: PoolOptions, dial: (origin: Origin) => Result<Stream, HttpError>): Pool requires options.perOrigin> = 0 && options.total> = 0 && options.idleMs> = 0 { const empty: Vec<Parked> = []
```

A Pool whose new connections come from `dial`, which connects to an
origin and secures it when it is https.

Effects: fail, write.

### `asset`

```gizlang
function asset(extension: string, contentType: string, body: bytes): Asset
```

An asset with BODY at a content-addressed path: the SHA-256 of BODY, then EXTENSION. Thus the path changes when the body changes, and the asset can be cached for ever.

Effects: fail.

### `pathOf`

```gizlang
function pathOf(request: Request): string
```

The request's path without its query.

Effects: fail.

### `query`

```gizlang
function query(request: Request): Params throws HttpError
```

The query parameters of a request: `decodeForm` of the text after "?".

Effects: fail.

### `decodeForm`

```gizlang
function decodeForm(encoded: string): Params throws HttpError
```

The pairs of an application/x-www-form-urlencoded text (a form body or a
query), decoded, in order, with all duplicate values ("+" is a space).
Empty parts are skipped. Invalid encoding or excess input returns 400.

Effects: fail.

### `partLimits`

```gizlang
function partLimits(): PartLimits
```

64 parts, 8 KiB heads, 1 MiB fields, 16 MiB files and 64 MiB in all.

Effects: fail.

### `multipart`

```gizlang
function multipart(contentType: string, limits: PartLimits): Multipart throws HttpError
```

The parser of a body with CONTENT_TYPE; 400 when it is not multipart/form-data with a valid boundary.

Effects: fail.

### `dispositionFilename`

```gizlang
function dispositionFilename(value: string): Option<string>
```

The file name a Content-Disposition value gives (RFC 6266): `filename*` (RFC 8187, UTF-8'' and percent escapes)
before `filename`; none when it gives none.

Effects: fail.

### `attachment`

```gizlang
function attachment(name: string): string
```

The Content-Disposition value that saves a download as `name` (RFC 6266): `filename` in printable ASCII ('"' and '\'
as '_'), and `filename*` with the whole name in UTF-8.

Effects: fail.

### `encode`

```gizlang
function encode(text: string): string
```

Percent-encoding (RFC 3986): every byte but A-Z a-z 0-9 - . _ ~ as %XX, so
the text is one query value or path segment. `decode` reads it back.

Effects: fail.

### `decode`

```gizlang
function decode(encoded: string, plusIsSpace: bool): Option<string>
```

Percent-decoding (RFC 3986); none for a bad escape or a result that is not
UTF-8. In a query, "+" also stands for a space.

Effects: fail.

### `under`

```gizlang
function under(path: string, prefix: string): Option<string>
```

The rest of `path` below `prefix` ("/static/a.css" under "/static" is
"/a.css"); none when the path is not there. A prefix matches whole
segments only: "/static" does not take "/statics".

Effects: fail.

### `redirect`

```gizlang
function redirect(status: i64, location: string): Response
```

A redirect with STATUS to LOCATION. The body is the location as plain text.

Effects: fail.

### `withHeader`

```gizlang
function withHeader(response: Response, name: string, value: string): Response
```

The response with one more header.

Effects: fail.

### `httpDate`

```gizlang
function httpDate(ms: i64): string
```

An HTTP date (RFC 9110 5.6.7), as "Sun, 06 Nov 1994 08:49:37 GMT".

Effects: fail.

### `parseHttpDate`

```gizlang
function parseHttpDate(value: string, nowMs: i64): Option<i64>
```

RFC 9110 HTTP-date, including both obsolete forms. nowMs resolves the
RFC 850 two-digit year at the exact fifty-year calendar boundary.
UTC leap second 60 maps to the next representable Unix second.

Effects: fail.

### `mimeType`

```gizlang
function mimeType(path: string): string
```

The media type of a file by its extension; text types are UTF-8.

Effects: fail.

### `file`

```gizlang
function file(dir: Dir, request: Request, path: string, nowMs: i64): Response
```

Serve the file at `path` (still percent-encoded, as in the request) below
`dir`, as nginx serves `root`: GET and HEAD; "index.html" for a directory,
and a redirect to the slash form for a directory named without it; the
media type; ETag and Last-Modified with ordered HTTP preconditions; and one
byte range (206, or 416 past the end). nowMs is the caller's System.time()
instant, needed to resolve obsolete two-digit HTTP years. Paths
cannot leave `dir` or follow links (gizlang:system).

Effects: fail, io.

### `files`

```gizlang
function files(dir: Dir): Files
```

A cache of the files of DIR for static serving.

Effects: fail, write.

### `fileReply`

```gizlang
function fileReply(files: Files, request: Request, path: string, nowMs: i64): ReplyPlan
```

The same file policy as file(), with known-length bounded transport output.
A kept body answers from memory. A larger file holds the opened inode from
admission until emission; HEAD never reads its body. Publish files
immutably (a new name for new content): a kept file can answer its old
content for KEPT_VALID_MS after a change.

Effects: fail, read, write, io.

### `fileReplyWith`

```gizlang
function fileReplyWith(files: Files, request: Request, path: string, nowMs: i64, extra: Vec<Header>): ReplyPlan
```

`fileReply` with EXTRA headers on every answer that carries the file (a Cache-Control the caller knows, for one).

Effects: fail, read, write, io.

### `precompress`

```gizlang
function precompress(dir: Dir, names: Vec<string>): Result<bool, string>
```

Writes `name.gz` beside each of NAMES in DIR, for codedFor to answer with, as 0644: the files are public, and a server
running as another user reads them. gzip only: it is Gizlang, so serving code needs no native library on a deploy host;
`name.br` (brotli, a native library) is written at build time.

Effects: fail, io.

### `publicFile`

```gizlang
function publicFile(dir: Dir, path: string, data: bytes): Result<bool, string>
```

DATA as the public file PATH of DIR (0644).

Effects: fail, io.

### `notModified`

```gizlang
function notModified(request: Request, tag: string): bool
```

Whether the request's If-None-Match names `tag` (an ETag with its quotes):
"*", or a list of tags compared weakly (W/ ignored), as RFC 9110 says for
GET; the caller then answers 304 with the headers it would have sent.

Effects: fail.

### `entityTagMatches`

```gizlang
function entityTagMatches(value: string, tag: string, strong: bool): bool
```

Compare an HTTP ETag list. Quoted commas are opaque tag bytes. Malformed
lists do not match; weak tags participate only in weak comparison.

Effects: fail.

### `precondition`

```gizlang
function precondition(request: Request, tag: Option<string>, modified: Option<i64>, nowMs: i64): i64
```

RFC 9110 precondition order. Zero permits execution; a conditional status
is final. Invalid dates are ignored; timestamps compare at second precision.
nowMs is supplied by the caller for deterministic obsolete-year resolution.

Effects: fail.

### `rangeValidatorMatches`

```gizlang
function rangeValidatorMatches(value: string, tag: string, modified: i64, nowMs: i64): bool
```

If-Range accepts one strong ETag or an exactly matching HTTP date. A stale,
weak or malformed validator requires the complete representation.

Effects: fail.

### `cookie`

```gizlang
function cookie(request: Request, name: string): Option<string>
```

The value of the request's cookie `name`, as the browser sent it.

Effects: fail.

### `setCookie`

```gizlang
function setCookie(name: string, value: string, maxAge: Option<i64>, secure: bool): string throws string
```

Build a Set-Cookie value with Path=/, HttpOnly and SameSite=Lax.
maxAge is seconds: none makes a session cookie; zero deletes with an empty
value. secure adds Secure. Reject negative ages, non-token names and values
outside the unquoted cookie-octets of RFC 6265 section 4.1.1.

Effects: fail.

### `parseByteRange`

```gizlang
function parseByteRange(spec: string, size: i64): ByteRange
```

One half-open interval from RFC 9110's single byte-range grammar. Callers
choose whether to ignore malformed input (HTTP files) or reject it (S3).

Effects: fail.

### `proxy`

```gizlang
function proxy(pool: Pool, upstream: Origin, request: Request): Response
```

Forward the request to the upstream origin and return its response, as
nginx's proxy_pass with upstream keep-alive: the request goes on a kept
connection of `pool` (a new one only when none is idle), hop-by-hop
headers (RFC 9110 7.6.1) are dropped both ways, and the upstream's own
authority is sent as Host. 502 when it cannot be reached or answers badly.

Effects: fail, read, write, console, io.

### `plainPolicy`

```gizlang
function plainPolicy(): Policy
```

A policy that changes nothing.

### `balancer`

```gizlang
function balancer(pool: Pool, upstreams: Vec<Origin>, holdMs: i64): Balancer
```

A balancer that sends requests of POOL to UPSTREAMS and holds a failed upstream out for HOLD_MS.

Effects: fail, write.

### `bodyOver`

```gizlang
function bodyOver(request: Request, from: i64): bool
```

Whether the request has a body that is chunked or of at least FROM bytes, which a server may stream instead of holding.

Effects: fail.

### `play`

```gizlang
function play(plan: ReplyPlan, exchange: mut Exchange): bool throws HttpError
```

Runs a reply plan on an exchange.

Effects: fail, read, write, console, io.

### `withExtra`

```gizlang
function withExtra(headers: Vec<Header>, extra: Vec<Header>): Vec<Header>
```

HEADERS with each field of EXTRA whose name they lack.

Effects: fail.

### `proxied`

```gizlang
function proxied(request: Request): Request
```

The request proxy sends upstream: without hop-by-hop headers and Host.

Effects: fail.

### `returned`

```gizlang
function returned(response: Response): Response
```

The upstream's response as proxy returns it: without hop-by-hop headers.

Effects: fail.

### `forwarded`

```gizlang
function forwarded(request: Request, proto: string): Request
```

The request as an edge forwards it: the client's address (from the socket, never from the client) appended to X-Forwarded-For, and
the scheme and Host the client used in X-Forwarded-Proto and X-Forwarded-Host. What a client sent under those names is dropped.

Effects: fail.

### `logLine`

```gizlang
function logLine(request: Request, response: Response, ms: i64): string
```

An access log line at `ms` (milliseconds since 1970 UTC, System.time()):
time, request line, status, body bytes, referrer and user agent, as nginx's
combined format without the client address.

Effects: fail.

### `compressed`

```gizlang
function compressed(request: Request, response: Response): Response
```

Negotiate buffered gzip/identity through the shared coding policy. Both
variants vary on Accept-Encoding; no acceptable representation answers 406.
Already coded bytes and byte ranges retain their admitted representation.

Effects: fail.

### `acceptsEncoding`

```gizlang
function acceptsEncoding(request: Request, coding: string): bool
```

Content-coding admission shared by buffered and progressive responses.
Explicit codings override wildcard admission. Identity is acceptable by
default unless identity;q=0 or an unoverridden *;q=0 excludes it.

Effects: fail.

### `router`

```gizlang
function router<T>(declarations: Vec<Route<T>>): Router<T> throws string
```

Compiles DECLARATIONS into a router, or gives why they are not valid (a bad pattern, a duplicate route or a bound that is exceeded).

### `mount`

```gizlang
function mount<T, U>(prefix: string, declarations: Vec<Route<T>>, target: (part: T) => U): Vec<Route<U>>
```

DECLARATIONS of a part of an app placed under PREFIX ("" or "/admin"):
each pattern after the prefix, each target made by TARGET, so the part is
declared once and composed into any app's routes.

### `gzip`

```gizlang
function gzip<F>(request: Request, next: F): Response
```

Middleware is a function of the request and the next handler (any function
from Request to Response) that may answer itself, change the request it
passes on or change the response, as Actix's wrap or Express's use; they
compose by nesting, outermost first: gzip(request, (r) => logged(r, site)).
gzip compresses what the rest answers (compressed above).

### `webSocketAccept`

```gizlang
function webSocketAccept(key: string): string
```

The Sec-WebSocket-Accept value of a Sec-WebSocket-Key.

Effects: fail.

### `isWebSocket`

```gizlang
function isWebSocket(request: Request): bool
```

Whether `request` opens a WebSocket: a GET with Upgrade: websocket,
Connection: upgrade, version 13 and a 16-byte key.

Effects: fail.

### `webSocket`

```gizlang
function webSocket(request: Request, protocol: string, session: SocketSession): ReplyPlan
```

The reply that opens a WebSocket for `request` and runs `session` on it,
then closes it; 426 when the request does not open one (isWebSocket).
`protocol`, when not "", is the subprotocol it answers with. A web app's
cross-site openings are refused before this (Web.crossSite).

Effects: fail.

### `openWebSocket`

```gizlang
function openWebSocket(sys: System, stream: Stream, host: string, path: string, headers: Vec<Header>): WebSocket throws HttpError
```

Opens a WebSocket at `path` of `host` as a client on `stream`, sending
`headers` too (an Origin, a Sec-WebSocket-Protocol).

Effects: fail, write, io.

### `replyFields`

```gizlang
function replyFields(headers: Vec<Header>, length: i64, date: bytes): Vec<Header>
```

The fields of a reply on HTTP/2 or HTTP/3: lower case, without HTTP/1.1 connection fields, with a Date (from DATE, a "date: ...\r\n"
line, as the connection makes it) and a Content-Length when LENGTH is known.

Effects: fail.

### `huffmanDecode`

```gizlang
function huffmanDecode(tree: Huffman, data: bytes): bytes throws string
```

The text that the Huffman code `data` stands for; an error for a code that is invalid or padded wrong.

Effects: fail.

### `newQpack`

```gizlang
function newQpack(): Qpack
```

The QPACK state: build it once and share it.

Effects: fail.

### `qpackDecode`

```gizlang
function qpackDecode(q: Qpack, block: bytes): Vec<Header> throws string
```

The fields of a QPACK field section (RFC 9204 §4.5) that uses only the static table: the connection announces a dynamic table of
capacity 0, so a section that needs one is an error.

Effects: fail.

### `qpackBlock`

```gizlang
function qpackBlock(q: Qpack, fields: Vec<Header>): bytes
```

A QPACK field section for FIELDS that uses only the static table (literals, never Huffman coded).

Effects: fail.

### `requestOf`

```gizlang
function requestOf(fields: Vec<Header>, peer: string): Request throws string
```

The request that HTTP/2 or HTTP/3 header fields make (RFC 9113 §8.3, RFC 9114 §4.3); an error for a malformed set.

Effects: fail.

### `replyOn`

```gizlang
function replyOn(request: Request, plan: ReplyPlan, mux: Mux): bool
```

Runs the reply of `plan` for `request` on a multiplexed stream; whether the reply ended whole.

Effects: fail, read, write, console, io.

### `openH2`

```gizlang
function openH2(stream: Stream, host: string, secure: bool): H2Client throws HttpError
```

Starts HTTP/2 on `stream` for `host` (the :authority); `secure` says the scheme is https.

Effects: fail, io.

### `clientOf`

```gizlang
function clientOf(request: Request, proxies: Vec<string>): string
```

The client of a request: the socket's peer (the server sets it, PEER_HEADER), or, when the peer is one of `proxies`, the last X-Forwarded-For value, which that proxy appended (the values before it came from the client and can be forged). Empty when the peer is not known.

Effects: fail.

### `limiter`

```gizlang
function limiter(limit: i64, windowMs: i64, proxies: Vec<string>): Limiter
```

A limiter of LIMIT requests from one client within WINDOWMS; PROXIES are the addresses whose X-Forwarded-For hop
names the client.

Effects: fail, write.

## Methods

### `Response.plan`

```gizlang
function Response.plan(self: Response): ReplyPlan
```

A buffered reply: the response as it is.

### `ReplyPlan.plan`

```gizlang
function ReplyPlan.plan(self: ReplyPlan): ReplyPlan
```

The plan itself.

### `Exchange.next`

```gizlang
function Exchange.next(self: mut Exchange): Option<bytes> throws HttpError
```

The next piece of the request body, or none at its end.

Effects: fail, read, write, console, io.

### `Exchange.whole`

```gizlang
function Exchange.whole(self: mut Exchange): Request throws HttpError
```

The whole request with its body read.

Effects: fail, read, write, console, io.

### `Exchange.acceptBody`

```gizlang
function Exchange.acceptBody(self: Exchange): bool throws HttpError
```

Send 100 Continue only after the application admits the request head.

Effects: fail, io.

### `Exchange.respond`

```gizlang
function Exchange.respond(self: mut Exchange, status: i64, headers: Vec<Header>, size: i64): bool throws HttpError
```

Writes the status line and HEADERS of a reply with SIZE body bytes. UNKNOWN_LENGTH gives a chunked body.

Effects: fail, read, write, console, io.

### `Exchange.write`

```gizlang
function Exchange.write(self: mut Exchange, data: bytes): bool throws HttpError
```

Writes DATA as part of the response body. It fails before the response starts, after it ends, or past its length.

Effects: fail, read, write, console, io.

### `Exchange.writeAll`

```gizlang
function Exchange.writeAll(self: mut Exchange, data: bytes): bool throws HttpError
```

Emit existing bytes as bounded pieces. No second framing or buffering owner.

Effects: fail, read, write, console, io.

### `Exchange.send`

```gizlang
function Exchange.send(self: mut Exchange, response: Response): bool throws HttpError
```

Buffered response emission through the same Exchange framing owner.

Effects: fail, read, write, console, io.

### `Exchange.trailers`

```gizlang
function Exchange.trailers(self: mut Exchange, fields: Vec<Header>): bool throws HttpError
```

Ends an HTTP/2 reply with trailer fields (a HEADERS frame that ends the stream), after respond and any write; gRPC's status
travels so. HTTP/1.1 replies have none.

Effects: fail, read, write, console, io.

### `Exchange.finish`

```gizlang
function Exchange.finish(self: mut Exchange): bool throws HttpError
```

Ends the response. It fails when the body is shorter than the length that the response said.

Effects: fail, read, write, console, io.

### `Outgoing.write`

```gizlang
function Outgoing.write(self: mut Outgoing, data: bytes): bool throws HttpError
```

Writes DATA as part of the request body. It fails after finish or past the length.

Effects: fail, io.

### `Outgoing.finish`

```gizlang
function Outgoing.finish(self: mut Outgoing): Incoming throws HttpError
```

Ends the request and reads the head of the response. It fails when the body is shorter than its length.

Effects: fail, write, io.

### `Incoming.next`

```gizlang
function Incoming.next(self: mut Incoming): Option<bytes> throws HttpError
```

The next piece of the body; none after the last.

Effects: fail, read, write, console, io.

### `Incoming.rest`

```gizlang
function Incoming.rest(self: mut Incoming): bytes throws HttpError
```

The rest of the body, at most MOST_BODY bytes.

Effects: fail, read, write, console, io.

### `Incoming.restUpTo`

```gizlang
function Incoming.restUpTo(self: mut Incoming, most: i64): bytes throws HttpError
```

The rest of the body, at most `most` bytes (a client reading a large answer).

Effects: fail, read, write, console, io.

### `Incoming.event`

```gizlang
function Incoming.event(self: mut Incoming): Option<Event> throws HttpError
```

The next server-sent event; none at the end of the stream. Comment lines
(":" first, as keep-alives) and events without data are skipped; a line
ends at LF, CRLF or CR.

Effects: fail, read, write, console, io.

### `Incoming.close`

```gizlang
function Incoming.close(self: Incoming): void
```

End the connection, unless it was given back to its Pool or is closed.

Effects: fail, read, write, io.

### `Incoming.whole`

```gizlang
function Incoming.whole(self: mut Incoming): Response throws HttpError
```

The whole response. After its body a pooled connection goes back to its
Pool, and any other connection is closed.

Effects: fail, read, write, console, io.

### `Feed.skipBody`

```gizlang
function Feed.skipBody(self: mut Feed): void
```

The current message has no body after all (a response to HEAD, which only its requester knows).

### `Feed.bodiless`

```gizlang
function Feed.bodiless(self: Feed): bool
```

The message whose head the feed just gave has no body (no Transfer-Encoding, and no or a zero Content-Length): its
next result is its end.

### `Feed.untilClose`

```gizlang
function Feed.untilClose(self: Feed): bool
```

The body runs until the peer closes; at that close the message ends.

### `Feed.push`

```gizlang
function Feed.push(self: mut Feed, data: bytes): void
```

Adds bytes read from the peer.

Effects: fail.

### `Feed.pending`

```gizlang
function Feed.pending(self: Feed): i64
```

The bytes pushed and not parsed yet.

Effects: fail.

### `Feed.rest`

```gizlang
function Feed.rest(self: Feed): bytes
```

Those bytes themselves: what follows an upgrade's head belongs to the new protocol (node:http's 'upgrade' head).

Effects: fail.

### `Feed.next`

```gizlang
function Feed.next(self: mut Feed): Parsed
```

The next result of the pushed bytes. A step that needs more bytes leaves the feed as it was, so it starts again
when they come.

Effects: fail, io.

### `Origin.authority`

```gizlang
function Origin.authority(self: Origin): string
```

The Host field of a request to the origin (RFC 9110 7.2): the host, in
brackets when it is an IPv6 literal, then ":port" unless the port is the
default of the scheme (80, or 443 for https).

Effects: fail.

### `Url.text`

```gizlang
function Url.text(self: Url): string
```

The URL written out, the port only when it is not the scheme's.

Effects: fail.

### `Url.resolve`

```gizlang
function Url.resolve(self: Url, location: string): Option<Url>
```

`location` (a redirect's: absolute, scheme-relative, a path or relative to
this one's directory) read against this URL.

Effects: fail.

### `Url.origin`

```gizlang
function Url.origin(self: Url): Origin
```

The origin of the URL, for a Pool.

### `Pool.idle`

```gizlang
function Pool.idle(self: Pool): i64
```

The idle connections the pool keeps now (none past the idle time).

Effects: fail, read, io.

### `Pool.close`

```gizlang
function Pool.close(self: Pool): void
```

Close the idle connections, and refuse new requests. A connection still
lent to an Incoming is closed when that Incoming ends.

Effects: fail, read, write, io.

### `Pool.open`

```gizlang
function Pool.open(self: Pool, origin: Origin, request: Request): Incoming throws HttpError
```

Send `request` to `origin` on a pooled connection and read the response
head; the body is then read from the Incoming. The request's own
`connection: close` is sent and ends the connection after the response.
An idle connection can be stale (its server closed it while it waited):
when such a reused connection ends before any byte of a response, an
idempotent request is sent one more time, on a new connection. No other
failure is sent again.

Effects: fail, read, write, console, io.

### `Pool.openAs`

```gizlang
function Pool.openAs(self: Pool, origin: Origin, host: string, request: Request, waitMs: i64): Incoming throws HttpError
```

`open` with `host` as the Host the origin is sent (a proxy that keeps the client's own), and the response head awaited at most `waitMs`
milliseconds (0: without a limit).

Effects: fail, read, write, console, io.

### `Pool.fetch`

```gizlang
function Pool.fetch(self: Pool, origin: Origin, request: Request): Response throws HttpError
```

The whole response of a pooled request.

Effects: fail, read, write, console, io.

### `Multipart.push`

```gizlang
function Multipart.push(self: mut Multipart, data: bytes): Vec<PartEvent> throws HttpError
```

The events that DATA completes. A malformed body is 400; a body over a bound is 413.

Effects: fail.

### `Multipart.finish`

```gizlang
function Multipart.finish(self: Multipart): bool throws HttpError
```

400 when the body ended before its closing delimiter.

### `Exchange.multipart`

```gizlang
function Exchange.multipart(self: Exchange, limits: PartLimits): Multipart throws HttpError
```

The parser of this exchange's multipart/form-data body within LIMITS, after 100 Continue when the client
expects it. `parts` then reads the body with it.

Effects: fail, io.

### `Exchange.parts`

```gizlang
function Exchange.parts(self: mut Exchange, parser: mut Multipart): Option<Vec<PartEvent>> throws HttpError
```

The events of the next piece of the body as it arrives, and none at its end (400 when PARSER has not seen
the closing delimiter). The body is never held whole: the caller keeps what it needs.
    let parser = try exchange.multipart(Http.partLimits());
    while (true) { match (try exchange.parts(parser)) { Option.some(events) => { ... } Option.none() => { break; } } }

Effects: fail, read, write, console, io.

### `Balancer.under`

```gizlang
function Balancer.under(self: Balancer, policy: Policy): Balancer
```

The same balancer (its upstreams, marks and turn are shared) under `policy`.

### `Balancer.standing`

```gizlang
function Balancer.standing(self: Balancer, standby: Vec<Origin>): Balancer
```

The same balancer with STANDBY: upstreams that get a request only when no upstream can take it (for example a server that starts
the upstream that is down).

### `Balancer.use`

```gizlang
function Balancer.use(self: Balancer, upstreams: Vec<Origin>): void
```

Replace the upstreams (for example the live members of a mesh, as they change). The marks of unreachable ones are cleared.

Effects: fail, write.

### `Balancer.follow`

```gizlang
function Balancer.follow(self: Balancer, members: Vec<Member>): void
```

Follow a mesh: the upstreams become the live members, at their `meta` port (as a number) on their host. Call it before a send with
`mesh.alive()`; a member whose meta is not a port is left out.

Effects: fail, write.

### `Balancer.keepingHost`

```gizlang
function Balancer.keepingHost(self: Balancer): Balancer
```

The same balancer (its upstreams, marks and turn are shared) that sends the request's own Host to the upstream, as a reverse proxy
does for sites that tell their hosts apart.

### `Balancer.open`

```gizlang
function Balancer.open(self: Balancer, request: Request): Incoming throws HttpError
```

The response head of the next upstream in turn that can be reached, its body still to be read. A request that no upstream took
(no connection was made, or it was refused) goes to the next. An idempotent request (GET, HEAD, OPTIONS, PUT, DELETE) that failed
on one goes to the next too, and one that got a status of the policy's `retryOn` goes again (to the next upstream, the same one
when it is alone) up to `retries` more times; another request is not sent twice.

Effects: fail, read, write, console, io.

### `Balancer.send`

```gizlang
function Balancer.send(self: Balancer, request: Request): Response
```

The answer of the next upstream in turn that can be reached (as `proxy`), or 502 when none can.

Effects: fail, read, write, console, io.

### `Balancer.relay`

```gizlang
function Balancer.relay(self: Balancer, request: Request, relay: Relay): ReplyPlan
```

The answer of the next upstream in turn that can be reached, as it arrives: the status and headers go on at once and each piece of
the body as the upstream delivers it (a download, an event stream), so nothing is held back and no size is bounded. A request
that asks to upgrade the connection (a WebSocket) is joined to the upstream's: after its 101 the two carry bytes both ways.

Effects: fail, read, write, console, io.

### `Balancer.forward`

```gizlang
function Balancer.forward(self: Balancer, request: Request, relay: Relay): ReplyPlan
```

The reply for a request whose body is still on the client's connection: the body goes to the first upstream that can be reached
as it arrives (its Content-Length, else chunked), so nothing is held and no size is bounded. A body sent cannot be sent again, so
only the dial can fall to the next upstream, and a failure after the first byte is a 502.

### `Router.resolve`

```gizlang
function Router.resolve<T>(self: Router<T>, request: Request): Routed<T> throws Response
```

Resolve exactly once. Path specificity is decided before method lookup: a
recognized static path with a different method is 405, not a capture fallback.
HEAD uses its explicit binding before GET; the HTTP writer suppresses its body.

### `Route.href`

```gizlang
function Route.href<T>(self: Route<T>, params: Params): string throws string
```

The path of this route with PARAMS: the declaration is the one source of
a link, not a second pattern string. Capture values are decoded values: a
segment's slash is escaped, a rest's slashes are kept as intentional
boundaries. Query fields use encode separately.

### `Params.get`

```gizlang
function Params.get(self: Params, name: string): string
```

A parameter's value, the first one for a name ("" when there is no such name).

Effects: fail.

### `Params.all`

```gizlang
function Params.all(self: Params, name: string): Vec<string>
```

Every value of a name, in order.

Effects: fail.

### `Params.integer`

```gizlang
function Params.integer(self: Params, name: string): Option<i64>
```

A parameter as a decimal integer, none when it is not one.

Effects: fail.

### `WebSocket.closed`

```gizlang
function WebSocket.closed(self: WebSocket): bool
```

Whether the socket is closed (by either side).

Effects: fail, read.

### `WebSocket.timeout`

```gizlang
function WebSocket.timeout(self: WebSocket, milliseconds: i64): i64 throws IoError
```

How long receive waits for the peer before it fails (IDLE_MS when opened).

Effects: fail, io.

### `WebSocket.send`

```gizlang
function WebSocket.send(self: WebSocket, message: string): bool throws HttpError
```

Sends a text message.

Effects: fail, read, io.

### `WebSocket.sendBytes`

```gizlang
function WebSocket.sendBytes(self: WebSocket, data: bytes): bool throws HttpError
```

Sends a binary message.

Effects: fail, read, io.

### `WebSocket.ping`

```gizlang
function WebSocket.ping(self: WebSocket, data: bytes): bool throws HttpError
```

Sends a ping; the peer's pong is consumed by receive.

Effects: fail, read, io.

### `WebSocket.close`

```gizlang
function WebSocket.close(self: WebSocket, code: i64, reason: string): bool
```

Sends a close frame once and marks the socket closed.

Effects: fail, read, write, io.

### `WebSocket.receive`

```gizlang
function WebSocket.receive(self: mut WebSocket): Option<Message> throws HttpError
```

The next message; none once the socket is closed (a close frame, the end
of the stream). A protocol violation closes the socket with its code and fails.

Effects: fail, read, write, io.

### `H2Client.start`

```gizlang
function H2Client.start(self: mut H2Client, method: string, path: string, headers: Vec<Header>, end: bool): bool throws HttpError
```

Opens a call: the request head, ending the stream when `end` says it has no body.

Effects: fail, io.

### `H2Client.send`

```gizlang
function H2Client.send(self: mut H2Client, data: bytes, end: bool): bool throws HttpError
```

The request body: `data` within the flow-control windows (it waits for the peer's WINDOW_UPDATE), the last piece with `end`.

Effects: fail, io.

### `H2Client.receive`

```gizlang
function H2Client.receive(self: mut H2Client): Option<bytes> throws HttpError
```

The next piece of the reply body; none when the reply ended (its trailers are in `trailers`).

Effects: fail, io.

### `H2Client.head`

```gizlang
function H2Client.head(self: mut H2Client): bool throws HttpError
```

Waits until the reply head arrived (`status`, `headers`).

Effects: fail, io.

### `H2Client.close`

```gizlang
function H2Client.close(self: mut H2Client): void
```

Closes the connection.

Effects: fail, io.

### `Limiter.admits`

```gizlang
function Limiter.admits(self: Limiter, request: Request): Option<Response>
```

Counts the request, or answers 429 with Retry-After in its place. A refused request is not counted. Clients quiet for a window are forgotten, so many addresses cannot grow the table.

Effects: fail, read, write, io.

### `Limiter.charges`

```gizlang
function Limiter.charges(self: Limiter, request: Request, units: i64): Option<Response>
```

`admits` for a request that costs UNITS of the limit (bytes in blocks, say): refused when the window cannot hold all of them. A cost over the whole limit counts as the limit.

Effects: fail, read, write, io.

### `Limiter.counted`

```gizlang
function Limiter.counted(self: Limiter, wallMs: i64, atLeast: i64): Vec<Counted>
```

The clients with at least `atLeast` requests in the window, as a store keeps them. `wallMs` is the wall clock now (System.time): the
limiter counts on a monotonic clock that restarts with the process. A client with few requests is not worth a row, and a restart
gives it a new budget it was far from using.

Effects: fail, read, io.

### `Limiter.restore`

```gizlang
function Limiter.restore(self: Limiter, counts: Vec<Counted>, wallMs: i64): void
```

Puts what `counted` kept back: each client's requests are spread evenly from its first to its last time, and the ones that have left the window by `wallMs` are dropped.

Effects: fail, read, write, io.

## Constants

### `STATUS_CONTINUE`

```gizlang
const STATUS_CONTINUE = 100
```

The status 100, Continue.

### `STATUS_SWITCHING_PROTOCOLS`

```gizlang
const STATUS_SWITCHING_PROTOCOLS = 101
```

The status 101, Switching Protocols.

### `STATUS_OK`

```gizlang
const STATUS_OK = 200
```

The status 200, OK.

### `STATUS_CREATED`

```gizlang
const STATUS_CREATED = 201
```

The status 201, Created.

### `STATUS_NO_CONTENT`

```gizlang
const STATUS_NO_CONTENT = 204
```

The status 204, No Content.

### `STATUS_PARTIAL_CONTENT`

```gizlang
const STATUS_PARTIAL_CONTENT = 206
```

The status 206, Partial Content.

### `STATUS_MOVED_PERMANENTLY`

```gizlang
const STATUS_MOVED_PERMANENTLY = 301
```

The status 301, Moved Permanently.

### `STATUS_FOUND`

```gizlang
const STATUS_FOUND = 302
```

The status 302, Found.

### `STATUS_SEE_OTHER`

```gizlang
const STATUS_SEE_OTHER = 303
```

The status 303, See Other.

### `STATUS_NOT_MODIFIED`

```gizlang
const STATUS_NOT_MODIFIED = 304
```

The status 304, Not Modified.

### `STATUS_TEMPORARY_REDIRECT`

```gizlang
const STATUS_TEMPORARY_REDIRECT = 307
```

The status 307, Temporary Redirect.

### `STATUS_PERMANENT_REDIRECT`

```gizlang
const STATUS_PERMANENT_REDIRECT = 308
```

The status 308, Permanent Redirect.

### `STATUS_REDIRECTION_START`

```gizlang
const STATUS_REDIRECTION_START = 300
```

The first status of the redirection class (300).

### `STATUS_BAD_REQUEST`

```gizlang
const STATUS_BAD_REQUEST = 400
```

The status 400, Bad Request.

### `STATUS_UNAUTHORIZED`

```gizlang
const STATUS_UNAUTHORIZED = 401
```

The status 401, Unauthorized.

### `STATUS_FORBIDDEN`

```gizlang
const STATUS_FORBIDDEN = 403
```

The status 403, Forbidden.

### `STATUS_NOT_FOUND`

```gizlang
const STATUS_NOT_FOUND = 404
```

The status 404, Not Found.

### `STATUS_METHOD_NOT_ALLOWED`

```gizlang
const STATUS_METHOD_NOT_ALLOWED = 405
```

The status 405, Method Not Allowed.

### `STATUS_NOT_ACCEPTABLE`

```gizlang
const STATUS_NOT_ACCEPTABLE = 406
```

406: no representation matches the request's Accept headers.

### `STATUS_CONFLICT`

```gizlang
const STATUS_CONFLICT = 409
```

The status 409, Conflict.

### `STATUS_PRECONDITION_FAILED`

```gizlang
const STATUS_PRECONDITION_FAILED = 412
```

The status 412, Precondition Failed.

### `STATUS_CONTENT_TOO_LARGE`

```gizlang
const STATUS_CONTENT_TOO_LARGE = 413
```

The status 413, Content Too Large.

### `STATUS_RANGE_NOT_SATISFIABLE`

```gizlang
const STATUS_RANGE_NOT_SATISFIABLE = 416
```

The status 416, Range Not Satisfiable.

### `STATUS_EXPECTATION_FAILED`

```gizlang
const STATUS_EXPECTATION_FAILED = 417
```

The status 417, Expectation Failed.

### `STATUS_TOO_MANY_REQUESTS`

```gizlang
const STATUS_TOO_MANY_REQUESTS = 429
```

The status 429, Too Many Requests.

### `STATUS_HEADER_FIELDS_TOO_LARGE`

```gizlang
const STATUS_HEADER_FIELDS_TOO_LARGE = 431
```

The status 431, Request Header Fields Too Large.

### `STATUS_INTERNAL_ERROR`

```gizlang
const STATUS_INTERNAL_ERROR = 500
```

The status 500, Internal Server Error.

### `STATUS_NOT_IMPLEMENTED`

```gizlang
const STATUS_NOT_IMPLEMENTED = 501
```

The status 501, Not Implemented.

### `STATUS_BAD_GATEWAY`

```gizlang
const STATUS_BAD_GATEWAY = 502
```

The status 502, Bad Gateway.

### `STATUS_SERVICE_UNAVAILABLE`

```gizlang
const STATUS_SERVICE_UNAVAILABLE = 503
```

The status 503, Service Unavailable.

### `STATUS_VERSION_NOT_SUPPORTED`

```gizlang
const STATUS_VERSION_NOT_SUPPORTED = 505
```

The status 505, HTTP Version Not Supported.

### `MOST_HEAD`

```gizlang
const MOST_HEAD = 65536
```

Bounds a peer cannot push past: the request or status line and headers,
and a body. A server holds at most 65,536 connections (gizlang:system's
Ready set); accepting waits beyond it.

### `MOST_BODY`

```gizlang
const MOST_BODY = 16777216
```

The most bytes of a message body.

### `BODY_PIECE`

```gizlang
const BODY_PIECE = 262144
```

The most bytes of a message body one read takes (a body streamed to disk is read in fewer, larger pieces).

### `IDLE_MS`

```gizlang
const IDLE_MS = 60000
```

A connection idle this long, or this slow sending a request, is closed.

### `PEER_HEADER`

```gizlang
const PEER_HEADER = "x-peer-address"
```

The header that carries the address of the socket's peer. The server sets it on every request and drops any that the client sent, so a handler can trust it; a proxy's own address is here, and the client behind it is the last X-Forwarded-For value.

### `MOST_PIECE`

```gizlang
const MOST_PIECE = 1048576
```

Maximum response piece. A request body read takes at most BODY_PIECE bytes.

### `UNKNOWN_LENGTH`

```gizlang
const UNKNOWN_LENGTH = -1
```

A streamed response whose size is not known before rendering begins.
respond/write/finish use HTTP chunk framing; the same Exchange owns both
known-size transfers and progressive rendering.

### `POOL_PER_ORIGIN`

```gizlang
const POOL_PER_ORIGIN = 64
```

The default most idle connections kept for one origin (connections in use are never limited), as nginx's
`keepalive 64`. Below the requests in flight to one origin, each surplus connection closes after its request and the
next one dials again: at 8, half the bench proxy's requests connected anew: 61k req/s instead of 158k.

### `POOL_TOTAL`

```gizlang
const POOL_TOTAL = 64
```

The default most idle connections that the pool keeps for all origins.

### `POOL_IDLE_MS`

```gizlang
const POOL_IDLE_MS = 30000
```

Less than the idle limit of common servers (nginx 75 s, gizlang:http's
IDLE_MS 60 s), so most idle connections are closed here first.

### `MAX_FORM_FIELDS`

```gizlang
const MAX_FORM_FIELDS = 1024
```

The most nonempty fields that `decodeForm` accepts.

### `MAX_FORM_BYTES`

```gizlang
const MAX_FORM_BYTES = 1048576
```

The most encoded bytes that `decodeForm` accepts.

### `MOST_KEPT_FILE`

```gizlang
const MOST_KEPT_FILE = 1048576
```

The most bytes of one file that a Kept cache holds.

### `MOST_KEPT_BYTES`

```gizlang
const MOST_KEPT_BYTES = 67108864
```

The most bytes that a Kept cache holds in all.

### `KEPT_VALID_MS`

```gizlang
const KEPT_VALID_MS = 1000
```

How long a kept file is served without a check, in milliseconds.

### `MIN_COMPRESS`

```gizlang
const MIN_COMPRESS = 256
```

Prefer identity for short bodies when the client admits it.

### `MAX_ROUTES`

```gizlang
const MAX_ROUTES = 4096
```

Admission bounds cover compilation and every request, including unsuccessful
searches. No regular expression or unbounded recursive backtracking is used.

### `MAX_ROUTE_DEPTH`

```gizlang
const MAX_ROUTE_DEPTH = 64
```

The most nested segments in one route.

### `MAX_ROUTE_NODES`

```gizlang
const MAX_ROUTE_NODES = 65536
```

The most nodes in the compiled route graph.

### `MAX_ROUTE_PATH`

```gizlang
const MAX_ROUTE_PATH = 8192
```

The longest request path that is matched, in bytes.

### `MAX_ROUTE_SEGMENTS`

```gizlang
const MAX_ROUTE_SEGMENTS = 128
```

The most segments in one request path.

### `MOST_MESSAGE`

```gizlang
const MOST_MESSAGE = 16777216
```

The largest message (all its frames) a peer may send.

### `CLOSE_NORMAL`

```gizlang
const CLOSE_NORMAL = 1000
```

Close codes (RFC 6455 §7.4.1).

### `CLOSE_PROTOCOL`

```gizlang
const CLOSE_PROTOCOL = 1002
```

The WebSocket close code 1002 (protocol).

### `CLOSE_INVALID`

```gizlang
const CLOSE_INVALID = 1007
```

The WebSocket close code 1007 (invalid).

### `CLOSE_TOO_BIG`

```gizlang
const CLOSE_TOO_BIG = 1009
```

The WebSocket close code 1009 (too big).

