# flare.http.response

> A module of flare_mlake's API.

HTTP response type.

## Structs

### `Status`

```mojo
struct Status
```

Common HTTP status code constants (RFC 7231 §6).

Implements: `Movable`

#### `OK`

```mojo
comptime OK = Int(200)
```

#### `CREATED`

```mojo
comptime CREATED = Int(201)
```

#### `ACCEPTED`

```mojo
comptime ACCEPTED = Int(202)
```

#### `NO_CONTENT`

```mojo
comptime NO_CONTENT = Int(204)
```

#### `MOVED_PERMANENTLY`

```mojo
comptime MOVED_PERMANENTLY = Int(301)
```

#### `FOUND`

```mojo
comptime FOUND = Int(302)
```

#### `NOT_MODIFIED`

```mojo
comptime NOT_MODIFIED = Int(304)
```

#### `TEMPORARY_REDIRECT`

```mojo
comptime TEMPORARY_REDIRECT = Int(307)
```

#### `PERMANENT_REDIRECT`

```mojo
comptime PERMANENT_REDIRECT = Int(308)
```

#### `BAD_REQUEST`

```mojo
comptime BAD_REQUEST = Int(400)
```

#### `UNAUTHORIZED`

```mojo
comptime UNAUTHORIZED = Int(401)
```

#### `FORBIDDEN`

```mojo
comptime FORBIDDEN = Int(403)
```

#### `NOT_FOUND`

```mojo
comptime NOT_FOUND = Int(404)
```

#### `METHOD_NOT_ALLOWED`

```mojo
comptime METHOD_NOT_ALLOWED = Int(405)
```

#### `REQUEST_TIMEOUT`

```mojo
comptime REQUEST_TIMEOUT = Int(408)
```

#### `CONTENT_TOO_LARGE`

```mojo
comptime CONTENT_TOO_LARGE = Int(413)
```

#### `URI_TOO_LONG`

```mojo
comptime URI_TOO_LONG = Int(414)
```

#### `HEADER_FIELDS_TOO_LARGE`

```mojo
comptime HEADER_FIELDS_TOO_LARGE = Int(431)
```

#### `INTERNAL_SERVER_ERROR`

```mojo
comptime INTERNAL_SERVER_ERROR = Int(500)
```

#### `BAD_GATEWAY`

```mojo
comptime BAD_GATEWAY = Int(502)
```

#### `SERVICE_UNAVAILABLE`

```mojo
comptime SERVICE_UNAVAILABLE = Int(503)
```

#### `GATEWAY_TIMEOUT`

```mojo
comptime GATEWAY_TIMEOUT = Int(504)
```

### `ResponseImpl`

```mojo
struct ResponseImpl[B: Body = InlineBody]
```

An HTTP/1.1 response, parameterised by its authoring body type ``B``.

``B`` is a *phantom* type parameter: it records the ``Body`` impl a
handler authored the response with (for the typed ``Handler.BodyType``
UX) but does not change the runtime layout. The body is always carried
by the erased carrier fields ``body`` (buffered bytes) or
``body_stream`` (a boxed streaming source), which is the single
representation every wire driver consumes. Because a bare
defaulted struct name is not itself concrete, the ergonomic
public spelling is the ``comptime Response =
ResponseImpl[InlineBody]`` alias below; all existing call sites keep
working unchanged through it. Typed authoring builds
``ResponseImpl[SomeBody]`` and calls :meth:`lower` at the wire
boundary to obtain the erased ``Response``.

Fields:
    status: HTTP status code (see ``Status.*`` constants).
    reason: Status reason phrase (e.g. ``"OK"``).
    headers: Response headers (owned ``HeaderMap``).
    body: Response body bytes.
    version: HTTP version string (default ``"HTTP/1.1"``).
    trailers: Response trailer fields (RFC 7230 §4.1.2). Empty
        for non-chunked responses; populated by the client when
        decoding a chunked response that carries trailer fields
        after the final chunk. Server-side trailer emission
        uses :class:`StreamingResponse[B].trailers` instead --
        buffered :class:`Response` always frames with
        ``Content-Length`` so it never carries trailers
        outbound.

This type is ``Movable`` (owns headers and body) but not ``Copyable``.

Example:
```mojo
var resp = client.get("http://example.com")
if resp.ok():
    print(resp.text())
# Trailers (gRPC-style status, etc) are populated when the
# peer sent ``Transfer-Encoding: chunked`` with trailing
# fields after the zero chunk:
var grpc_status = resp.trailers.get("grpc-status")
```

Implements: `Movable`

Fields:

- `status: Int`
- `reason: String`
- `headers: HeaderMap`
- `body: List[UInt8]`
- `version: String`
- `trailers: HeaderMap`
- `body_stream: Optional[ChunkSourceBox]`: Optional streaming body source (K1). ``None`` for the ordinary buffered response (the ``body`` field carries the bytes); ``Some`` when a handler returns a streaming response, in which case the reactor emits ``Transfer-Encoding: chunked`` headers and pulls this source a bounded batch of chunks at a time per writable edge instead of sending ``body``. Move-only, so ``Response`` stays move-only.

#### `__init__`

```mojo
def __init__(out self, status: Int, var reason: String = "", var body: List[UInt8] = List(), var version: String = "HTTP/1.1")
```

#### `reset`

```mojo
def reset(mut self, status: Int = Int(200), var reason: String = "")
```

Recycle this ``Response`` in place for the next request on a keep-alive connection.

Clears the body and header maps without releasing their
backing capacity — the next response can refill the same
``List[UInt8]`` body and the same ``HeaderMap`` arrays
without re-allocating, as long as the new payload fits
in the prior capacity.

The version is left at ``"HTTP/1.1"``; callers that need a
non-default version can set ``self.version`` directly.

Args:

- `status`: New status code (default 200).
- `reason`: New reason phrase (default empty —
        ``_status_reason`` will fill from the status
        code at serialise time).

#### `ok`

```mojo
def ok(self) -> Bool
```

Return True if the status code is 2xx.

#### `is_redirect`

```mojo
def is_redirect(self) -> Bool
```

Return True if the status code is a redirect (3xx).

#### `text`

```mojo
def text(self) -> String
```

Decode the body as a UTF-8 string.

Interprets the body bytes as UTF-8. Invalid UTF-8 sequences are
replaced with the Unicode replacement character (best-effort).

#### `json`

```mojo
def json(self) -> Value
```

Parse the body as JSON and return a ``json.Value``.

Uses the pure-Mojo backend from
`json <https://github.com/ehsanmok/json>`_.

Example:
```mojo
var resp = client.get("https://httpbin.org/json")
var data = resp.json()
print(data["slideshow"]["title"].string_value())
```

Raises: Error: If the response body is not valid JSON.

#### `raise_for_status`

```mojo
def raise_for_status(self)
```

Raise ``HttpError`` if the status code is not 2xx.

A no-op for responses with ``200 <= status < 300``.

Example:
```mojo
var resp = client.get("https://httpbin.org/status/404")
resp.raise_for_status() # raises HttpError: 404 Not Found
```

Raises: HttpError: If the status code indicates an error (< 200 or >= 300).

#### `set_cookie`

```mojo
def set_cookie(mut self, var cookie: Cookie)
```

Append a ``Set-Cookie`` response header for ``cookie``.

Multiple cookies are emitted as separate ``Set-Cookie`` lines
per RFC 6265 paragraph 3, never folded into a single header.

Args:

- `cookie`: The cookie to set (ownership taken).

#### `cookies`

```mojo
def cookies(self) -> CookieJar
```

Parse all ``Set-Cookie`` headers into a ``CookieJar``.

Each ``Set-Cookie`` header is parsed independently with
``parse_set_cookie_header`` (attributes preserved). Returns
an empty jar when no ``Set-Cookie`` headers are present.

#### `iter_bytes`

```mojo
def iter_bytes(self, chunk_size: Int = Int(8192)) -> _BytesIter
```

Return an iterator that yields the body in chunks.

The entire body is already buffered in memory, so this does not
perform additional I/O. Useful for streaming-style processing.

Example:
```mojo
for chunk in resp.iter_bytes(1024):
    process(chunk[])
```

Args:

- `chunk_size`: Maximum bytes per chunk (default 8192).

#### `lower`

```mojo
def lower(deinit self) -> ResponseImpl
```

Erase the phantom body type, yielding the concrete ``Response`` (``ResponseImpl[InlineBody]``) that every wire driver consumes.

``B`` never affected the layout, so this moves every field across
unchanged -- no copy of the body bytes or the stream box. Typed
handlers that author a ``ResponseImpl[SomeBody]`` call this at the
wire boundary to hand the reactor the single erased representation.

Uses the ``deinit self`` convention so the fields can be moved out
and repacked into the ``InlineBody`` binding without a copy.

## Functions

### `stream_response`

```mojo
def stream_response[S: ChunkSource](var source: S, status: Int = Int(200)) -> Response
```

Build a streaming ``Response`` backed by ``source`` (K1).

The reactor serves this with ``Transfer-Encoding: chunked``,
pulling ``source.next(cancel)`` in bounded batches per writable edge
until it returns ``None`` (end-of-stream), so an open-ended or large
body never has to materialise in memory. A source with nothing ready
returns an empty chunk to end the batch. Set response headers (e.g.
``Content-Type: text/event-stream`` for SSE) on the returned value
before returning it from a handler.

Args:

- `source`: The chunk source; ownership transfers in.
- `status`: HTTP status code (default 200).

### `response_from_body`

```mojo
def response_from_body[B: Body](var body: B, status: Int = Int(200), var reason: String = "") -> Response
```

Build a concrete ``Response`` from any ``Body`` impl (opt-in ``Response[B]`` ergonomics).

Known-length bodies (``content_length()`` is ``Some``) are drained into
the buffered ``Response.body`` -- byte-identical to the ordinary
``Response`` path. Open-ended bodies (``None``) are attached to
``body_stream`` so the reactor emits ``Transfer-Encoding: chunked`` and
pulls chunks on writable edges. Set headers on the returned value before
returning it from a ``Handler``.

Args:

- `body`: The body source; ownership transfers in.
- `status`: HTTP status code (default 200).
- `reason`: Status reason phrase (default empty -> filled at serialise).

## Aliases

### `Response`

```mojo
comptime Response = ResponseImpl
```

The concrete, body-type-erased HTTP response every wire driver consumes.

This is the ergonomic public spelling of :struct:`ResponseImpl` bound to
:struct:`InlineBody`. Because a bare defaulted struct name
(``ResponseImpl``) is not itself concrete, ``Response`` is
provided as a ``comptime`` alias -- all existing ``Response(...)`` /
``-> Response`` / ``Optional[Response]`` sites resolve through it
unchanged. Handlers that want the typed authoring surface build a
``ResponseImpl[SomeBody]`` and call ``.lower()`` to obtain this type.
