Capy-Bearer Documentation

Request

Capy

handler request : any

Every Capy handler binds request implicitly as an any. You can also declare request : any explicitly. 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)

Output

No output

Use the ? suffix to test whether a value is not none. A missing key and an existing key containing none both return false. Use has(request.query, "token") when you need key existence:

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

Output

No output

Fields

FieldTypeContains
methodstringGET, POST, and so on
querymapparsed query-string parameters
formmapparsed form body parameters
paramsmapmerged query and form parameters. Form values win when keys match.
bodystringthe raw request body
headersmaprequest headers, lowercased with dashes: content-type, x-request-id
cookiesmaprequest cookies by name
filesarrayuploaded files, each with field, name, size, temporary_path
routemappath, page, raw_path, valid
urlmapscript, base
servermapremaining server and CGI variables, original uppercase names
sessionmapsession state, updated by session effects
configmaprequest-visible configuration, including start_directory
connectionmapconnection information
unitstringentry unit source path
websocketmapcurrent connection_id, scope, opcode, binary, connections
callmapcurrent dispatch information
outmapresponse status, headers, and cookies

Form and JSON bodies

request.form contains parsed form fields. JSON fields do not appear in request.form or request.params. Decode a JSON body explicitly:

var input := json_decode(string(request.body)).value
var title := string(input.title, fallback: "Untitled")

request.files contains multipart uploads. field is the form field name, and name is the client-supplied filename. temporary_path names the uploaded bytes on the server. Bearer removes temporary uploads after the request. Move a file with file_rename() if you need to keep it.

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 : any parameter. Components share the caller's props object. Tasks receive a serialized copy in another process.

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

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

Output

guest
if string(request.method) == "POST"
{
	print("saved ", request.form.answer, "\n")
}
else
{
	print("<form method=\"post\"><input name=\"answer\"></form>", "\n")
}

Output

<form method="post"><input name="answer"></form>
print(string(request.headers["user-agent"], fallback: "unknown"), "\n")
print(string(request.cookies.session, fallback: "none"), "\n")

Output

unknown
none
for file := request.files
{
	print(file.name, " ", u64(file.size), "\n")
}

Output

No output
if request.query.page?
{
	print("page ", s64(request.query.page, fallback: 1), "\n")
}
else
{
	print("no page requested\n")
}

Output

no page requested