Reference · Cookies and sessions

set_cookie

signature
set_cookie(str, any=, map | null=) -> null

What it does

Adds a Set-Cookie header to the request's answer, whatever the route returns, from anywhere in the request: a route, a server fn, a helper. The value is percent-encoded on the way out and decoded by cookie, so any text fits; a value that is not a string is written as text, and none as the empty string. The options are max_age, path, domain, http_only, secure and same_site, and another is an error; without them a cookie is HttpOnly, Secure, SameSite=Lax, for Path=/, and lasts until the browser closes. It gives null. The guide Headers, cookies and sessions has the options' table.

Examples

A page whose buttons post a choice, the route that keeps it in a cookie, and the page reading it back with cookie on the next visit. The button's name and value are the form's field:

in a program
route GET / {    let theme = cookie("theme") ?? "light"    <main class={theme}>        <form method="post" action="/theme">            <button name="theme" value="light">Light</button>            <button name="theme" value="dark">Dark</button>        </form>    </main>}route POST /theme { form: { theme: str } } {    if theme != "light" && theme != "dark" { reply 400 "No such theme" }   // a form can send anything    set_cookie("theme", theme, { max_age: "1y" })    redirect("/")}route POST /tz { form: { tz: str } } {    set_cookie("tz", tz, { max_age: "1y", http_only: false })   // the page's script may read it    { ok: true }}

Outside a request there is no answer to carry the cookie; the call still checks its arguments and gives null:

print(set_cookie("theme", "dark", { max_age: "30d" }))print(cookie("theme"))
output
nullnull

Edge cases

print(set_cookie("n", 42), set_cookie("n"), set_cookie("n", null))print(set_cookie("__Host-cart", "7", { max_age: "7d" }), set_cookie("a", "b", { same_site: "None", secure: false }))
output
null null nullnull null

Errors

A bad cookie name, a max_age that is not seconds or a duration, a path not starting with / or holding a space, a domain that is not a host name, a same_site other than "Lax", "Strict" or "None", an option it does not take, a prefixed cookie that breaks its prefix's rules, a cookie of more than 3,900 bytes, and options that are not a map are runtime errors, not error values.

this one fails
set_cookie("bad name", "x")
output
line 1: `set_cookie` needs a cookie name of letters, digits and -_.!#$%&'*+^`|~, got "bad name"
this one fails
set_cookie("a", "b", { same_site: "nope" })
output
line 1: `set_cookie`'s same_site is "Lax", "Strict" or "None", got "nope"
this one fails
set_cookie("theme", "dark", { sameSite: "Strict" })
output
line 1: `set_cookie` has no option `sameSite`: write it `same_site`
this one fails
set_cookie("__Host-cart", "7", { domain: "example.com" })
output
line 1: `set_cookie`: a `__Host-` cookie has no domain, as browsers take it only from the host that sets it; leave `domain` out

Chaining

set_cookie is a statement with a side effect, so it sits on its own line before the route's answer rather than in a pipeline. A helper can set a cookie and give its value back for the rest of the route:

in a program
fn remember_theme(theme: str) { set_cookie("theme", theme, { max_age: "1y" }); theme }route POST /theme { form: { theme: str } } = <Page theme={remember_theme(theme)}><Home/></Page>

See also

cookie, delete_cookie, set_session, respond

Thread
9Useful? Like it, or add to its thread below.

Thread 0 posts

On set_cookie(): questions, tips, corrections, and code that uses it.

No posts yet. The first one opens the thread.

    Edit this page on GitHub · every example's output was made by running it (tools/refcheck.mjs) · questions on Discord or r/quillo