:title
Request

:sig
handler request : dval

:content
Every Capy handler binds `request` implicitly as a `dval`. All handlers in a request receive the same object. Application keys written on it remain visible to later handlers.

Read scalars through a converter with a fallback, so a key that is absent has a defined value rather than an error:

    var name := string(request.query.name, fallback: "guest")
    var page := s64(request.query.page, fallback: 1)
    var debug := bool(request.query.debug)

Test for presence with the `?` suffix, which is `true` when the key exists:

    if request.query.token? { print("token supplied\n") }

## Fields

| Field | Type | Contains |
| --- | --- | --- |
| `method` | string | `GET`, `POST`, and so on |
| `query` | map | parsed query-string parameters |
| `form` | map | parsed form body parameters |
| `params` | map | merged query and form parameters. Form values win when keys match. |
| `body` | string | the raw request body |
| `headers` | map | request headers, lowercased with dashes: `content-type`, `x-request-id` |
| `cookies` | map | request cookies by name |
| `files` | array | uploaded files, each with `name`, `size`, `temporary_path` |
| `route` | map | `path`, `page`, `raw_path`, `valid` |
| `url` | map | `script`, `base` |
| `server` | map | remaining server and CGI variables, original uppercase names |
| `session` | map | session state, updated by session effects |
| `config` | map | request-visible configuration, including `start_directory` |
| `connection` | map | connection information |
| `unit` | string | entry unit source path |
| `websocket` | map | current `connection_id`, `scope`, `opcode`, `binary`, `connections` |
| `call` | map | current dispatch information |
| `out` | map | response `status`, `headers`, and `cookies` |

## Headers and server variables

`headers` holds anything that arrived as an HTTP header, renamed for readability: the transport's `HTTP_X_REQUEST_ID` appears as `request.headers["x-request-id"]`. `content-type` and `content-length` are included even though they arrive without the `HTTP_` prefix. Use bracket syntax for these, since the names contain dashes.

`request.config.start_directory` is the process start directory. It stays stable when a unit changes its current directory.

`server` holds everything else — `QUERY_STRING`, `REMOTE_ADDR`, `SERVER_NAME` — under the original uppercase names. `method`, `route`, and `url` are lifted out of `server` into their own fields, so look for them there rather than in `server`.

## Reading and writing

Bearer reserves `call`, `unit`, `out`, `session`, `websocket`, and `connection`. Bearer does not refresh request keys between handlers. Do not use them for application state. Add application keys such as `request.user` or `request.pagefacts` instead.

Set `request.out.status`, `request.out.headers`, or `request.out.cookies` to change the response. Bearer applies `request.out` once after the top handler finishes. `print()` appends to the response body.

Components and tasks receive input through a `props : dval` parameter. Components share the caller's props object. Tasks receive a serialized copy in another process.

Exported `(dval) dval` functions capture `request` implicitly. Ordinary helpers that need it declare `request : capture dval`.

:example capy render
print(string(request.query.name, fallback: "guest"), "\n")

:example capy render branch on the method and read a form field
if string(request.method) == "POST"
{
	print("saved ", string(request.form.answer), "\n")
}
else
{
	print("<form method=\"post\"><input name=\"answer\"></form>", "\n")
}

:example capy render read a header and a cookie
print(string(request.headers["user-agent"], fallback: "unknown"), "\n")
print(string(request.cookies.session, fallback: "none"), "\n")

:example capy render list uploaded files
for file := request.files
{
	print(string(file.name), " ", u64(file.size), "\n")
}

:example capy render check presence before use
if request.query.page?
{
	print("page ", s64(request.query.page, fallback: 1), "\n")
}
else
{
	print("no page requested\n")
}

:see-group
request

:see
>handler/render
>handler/cli
>handler/ws
string
