:title
9. Handling a web request

:content
Every handler binds `request` implicitly. Handlers in one request share the same request object.

## Read the request

:example capy render
function RENDER()
{
	var name := string(request.query.name, fallback: "guest")
	request.out.headers["Content-Type"] = "text/plain; charset=utf-8"
	print("Hello, ", name, "!\n")
}

:output
Hello, guest!

:content
The request contains `method`, `query`, `form`, `params`, `headers`, `cookies`, `body`, `files`, `route`, `url`, `server`, `session`, `config`, `call`, `connection`, `unit`, `websocket`, and `out`.

`route` contains `path`, `page`, `raw_path`, and `valid`. `url` contains `script` and `base`. `session` contains `id`, `name`, and `values`. `websocket` contains `connection_id`, `scope`, `opcode`, `binary`, and current-scope `connections`.

Missing members are `none`. Use normal conversions for scalar values. For example, use `string(request.form.email)`, `s32(request.websocket.opcode)`, and `bool(request.websocket.binary)`.

## Form a response

Use `print`, `request.out.status`, `request.out.headers`, `request.out.cookies`, and `redirect` to change the response. Use a redirect after a successful state change so the user can refresh the page safely.

Use `ws_send`, `ws_send_to`, and `ws_close` for WebSocket effects. Use `request.websocket.connections` to select current-scope clients.

## Handle a form

A handler normally uses one route for both the form and the POST result. Read `request.method` first. Read submitted fields from `request.form`.

This example shows the complete control flow. A GET request prints the form. A POST request validates the email, stores it in the session, queues a cookie, and redirects. Use `print` for every HTML string that the handler must send. The documentation renderer runs the GET path.

:example capy render
function RENDER()
{
	request.out.headers["Content-Type"] = "text/html; charset=utf-8"
	var method := string(request.method, fallback: "GET")

	if method == "POST"
	{
		var email := string(request.form.email)
		if email == ""
		{
			request.out.status = 422
			print(<><p>Email is required.</p></>)
			return
		}

		var session := session_start("account")
		session = session_set("email", email)
		request.out.cookies["has_account"] = "1"
		redirect("/account")
		return
	}

	print(<>
        <form method="post">
            <label>Email <input name="email" type="email" /></label>
            <button>Save</button>
        </form>
    </>)
}

:content

## Read uploaded files

Uploaded files appear in `request.files`. Each entry is a copied `dval` with the metadata that Bearer accepted for the request. Treat the original filename as user input.

Use the generated request page for the exact file fields. Validate the file count, size, and type before you store anything.

:example capy render
function RENDER()
{
	var files := request.files
	print("files=", length(files), "\n")
}

:content

## Sessions

Session effects return a state map with `id`, `name`, and `values`. `session_start`, `session_set`, `session_remove`, and `session_destroy` also update `request.session` in place.

:example capy render
function RENDER()
{
	var session := session_start("account")
	session = session_set("theme", "dark")
	print(string(session.values.theme), "\n")
}

:content

## CLI and WebSocket handlers

Use `CLI` for a local command through Bearer's private CLI socket. Read command input from the request:

:example capy cli
function CLI()
{
	print(string(request.body))
}

:content

Use `WS` for each WebSocket message. Read the message from `request.body`. Read the connection ID, scope, opcode, binary flag, and current-scope connections from `request.websocket`:

:example capy ws
function WS()
{
	ws_send(string(request.body), false)
}

:content

Use `function RENDER()`, `function CLI()`, `function WS()`, `function INIT()`, `function ONCE()`, and `function SERVE_HTTP()`.

Named render handlers also omit the request parameter. Components and tasks use `props : dval`, such as `function COMPONENT:CARD(props : dval)` and `function TASK:STORE(props : dval)`.

Handlers do not return application values. Bearer does not refresh request keys between handlers. `request.unit` identifies the entry unit throughout the request.

Bearer applies `request.out` once after the top handler finishes. Components and exports can change the same response object.

:see-group
guides

:see
type/request
handler/render
handler/cli
session_start
capy-08-dynamic-values
capy-10-units-components-and-exports
session_set
session_remove
type/bool
type/s32
string
