# flare.http3.request_writer

> A module of flare_mlake's API.

HTTP/3 request-stream writer -- sans-I/O byte emitter.

The client-side mirror of :mod:`flare.http3.response_writer`. Builds
the bytes an HTTP/3 client hands to the QUIC stream layer for a
request on a client-initiated bidirectional stream, plus the
preambles for the client's unidirectional control + QPACK streams.

A complete H3 request is at most three concatenated wire fragments
on the request (bidi) stream:

  HEADERS frame (``:method`` / ``:scheme`` / ``:authority`` /
                 ``:path`` pseudo-headers + application headers,
                 QPACK-encoded)
  DATA frame    (zero or more, request body)
  HEADERS frame (optional trailers, QPACK-encoded)

Before any request, the client opens three unidirectional streams
(RFC 9114 §6.2): the control stream (type 0x00, carrying SETTINGS
first) and the QPACK encoder / decoder streams (types 0x02 / 0x03,
empty in the static-only table mode flare uses). The preamble
encoders here emit the leading stream-type varint + initial frame
so the caller can ship them as the first bytes of each uni-stream.

Public surface:

* :func:`encode_request_headers` -- the initial HEADERS frame with
  the four request pseudo-headers in canonical order (RFC 9114
  §4.3.1) followed by the application headers (lowercased).
* :func:`encode_request_data` -- wrap a body chunk in a DATA frame.
* :func:`encode_request_trailers` -- the trailing HEADERS frame.
* :func:`encode_client_control_stream` -- the control-stream type
  byte + the client's SETTINGS frame (the mandatory first frame,
  RFC 9114 §6.2.1).
* :func:`encode_qpack_encoder_stream` / :func:`encode_qpack_decoder_stream`
  -- the single stream-type byte for each QPACK uni-stream.

Sans-I/O contract: every entry point is a pure function over its
inputs; the QUIC client driver owns the per-stream cursor + FIN.

References:
- RFC 9114 §4 (HTTP Message Exchanges) + §6.2 (uni-streams) + §7.
- RFC 9204 (QPACK) -- static-table field-section encoder.

## Functions

### `encode_request_headers`

```mojo
def encode_request_headers(method: String, scheme: String, authority: String, path: String, headers: List[HpackHeader], mut out: List[UInt8], protocol: String = "")
```

Append the HEADERS-frame bytes for an HTTP/3 request to ``out``. A non-empty ``protocol`` adds ``:protocol`` (an extended CONNECT, RFC 9220).

Emits the four request pseudo-headers ``:method`` / ``:scheme``
/ ``:authority`` / ``:path`` in canonical order (RFC 9114
§4.3.1) before the supplied application headers (all names
lowercased). The caller MUST NOT include any pseudo-header in
``headers`` -- the writer rejects a name starting with ``:``
there, mirroring :func:`flare.http3.response_writer.encode_response_headers`.

``authority`` may be empty for the ``CONNECT``-less origin case
where a ``Host`` header is used instead, but for normal
requests it carries the ``host[:port]`` the request targets.

### `encode_request_data`

```mojo
def encode_request_data(payload: Span[UInt8], mut out: List[UInt8])
```

Append an HTTP/3 DATA frame wrapping ``payload`` to ``out``.

The client calls this once per body chunk. Empty payloads are
legal and encode as a 2-byte frame (type=0x00 + length=0x00).

### `encode_request_trailers`

```mojo
def encode_request_trailers(trailers: List[HpackHeader], mut out: List[UInt8])
```

Append the trailing HEADERS-frame bytes to ``out``.

Trailers MUST NOT include pseudo-headers; the writer rejects
any field whose name starts with ``:``. The driver sends this
frame followed by FIN to close the request side of the stream.

### `encode_client_control_stream`

```mojo
def encode_client_control_stream(max_field_section_size: UInt64, mut out: List[UInt8])
```

Append the client's control unidirectional stream preamble to ``out``: the stream-type varint (0x00) followed by the SETTINGS frame that MUST be the first frame (RFC 9114 §6.2.1).

flare runs QPACK in static-table-only mode, so the QPACK
capacity + blocked-streams settings are advertised as 0,
telling the server not to use the dynamic table against us.
The caller writes the returned bytes as the very first bytes of
a fresh client-initiated unidirectional stream.

### `encode_qpack_encoder_stream`

```mojo
def encode_qpack_encoder_stream(mut out: List[UInt8])
```

Append the QPACK encoder unidirectional stream type byte (0x02, RFC 9204 §4.2). No further bytes follow in static-only mode (no dynamic-table instructions are ever sent).

### `encode_qpack_decoder_stream`

```mojo
def encode_qpack_decoder_stream(mut out: List[UInt8])
```

Append the QPACK decoder unidirectional stream type byte (0x03, RFC 9204 §4.2). No further bytes follow in static-only mode.

## Aliases

### `H3_UNI_STREAM_CONTROL`

```mojo
comptime H3_UNI_STREAM_CONTROL = UInt64(0)
```

### `H3_UNI_STREAM_QPACK_ENCODER`

```mojo
comptime H3_UNI_STREAM_QPACK_ENCODER = UInt64(2)
```

### `H3_UNI_STREAM_QPACK_DECODER`

```mojo
comptime H3_UNI_STREAM_QPACK_DECODER = UInt64(3)
```
