#Cookie

    HTTP cookie parsing and serialization for MoonBit.

    Cookies are small pieces of data that web servers send to browsers via Set-Cookie headers. The browser stores them and attaches them back on subsequent requests in the Cookie header. They are the standard mechanism for session management, user preferences, and tracking across HTTP requests.

    #How Cookies Work

    Cookies rely on a two-step exchange between server and browser:

    1. Server sets a cookie — The server includes one or more Set-Cookie headers in an HTTP response. Each header carries a name-value pair plus optional attributes that control the cookie's lifetime, scope, and security:

    HTTP/1.1 200 OK Set-Cookie: session_id=abc123; Path=/; Max-Age=3600; Secure; HttpOnly; SameSite=Lax

    2. Browser sends it back — On every subsequent request to the same origin (subject to Path, Domain, and SameSite rules), the browser automatically attaches all matching cookies in a single Cookie header:

    GET /api/profile HTTP/1.1 Cookie: session_id=abc123; theme=dark

    The server never sees the attributes (Path, Secure, etc.) again — the browser uses them locally to decide whether to send the cookie, but only the name=value pairs travel back.

    AttributePurpose
    Max-AgeSeconds until the cookie expires. 0 deletes it immediately.
    PathURL path prefix the cookie applies to (default: current path).
    DomainWhich hosts receive the cookie (default: exact origin only).
    SecureOnly send over HTTPS.
    HttpOnlyHide from JavaScript (document.cookie), mitigating XSS.
    SameSiteControls cross-site sending — see SameSite Options.

    #Lifecycle

    1. Session cookies — no Max-Age or Expires: deleted when the browser closes.
    2. Persistent cookies — have a Max-Age (or Expires): survive across browser restarts until they expire.
    3. Deletion — the server sends Set-Cookie: name=; Max-Age=0 to ask the browser to remove a cookie.

    This package provides:

    • CookieItem — a typed representation of an HTTP cookie with attributes like Path, Domain, Max-Age, Secure, HttpOnly, and SameSite.
    • parse_cookie — parses a raw cookie header string into a map of cookie items.
    • cookie_to_string — serializes an array of cookies back into a header string.

    #Install

    This package is included with bobzhang/crescent. Import it directly:

    import { "bobzhang/crescent/cookie" ... }

    #Creating Cookies

    Use the CookieItem constructor to build a cookie with optional attributes:

    ///|
    test "create a cookie with attributes" {
    let cookie = @cookie.CookieItem(
    name="session_id",
    value="abc123",
    max_age=3600,
    path="/",
    domain="example.com",
    secure=true,
    http_only=true,
    same_site=Lax,
    )
    debug_inspect(
    cookie,
    content=(
    #|{
    #| name: "session_id",
    #| value: "abc123",
    #| max_age: Some(3600),
    #| path: Some("/"),
    #| domain: Some("example.com"),
    #| secure: Some(true),
    #| http_only: Some(true),
    #| same_site: Some(Lax),
    #|}
    ),
    )
    }

    A minimal cookie only needs name and value:

    ///|
    test "minimal cookie" {
    let cookie = @cookie.CookieItem(name="theme", value="dark")
    debug_inspect(
    cookie.to_string(),
    content=(
    #|"theme=dark"
    ),
    )
    }

    #Parsing Cookies

    parse_cookie parses a raw Cookie header string into a Map[String, CookieItem]:

    ///|
    test "parse a cookie header" {
    let cookies = @cookie.parse_cookie("name=value; session=abc123")
    debug_inspect(
    cookies.get("name").map(fn(c) { c.value }),
    content="Some(\"value\")",
    )
    debug_inspect(
    cookies.get("session").map(fn(c) { c.value }),
    content="Some(\"abc123\")",
    )
    }

    It also recognizes Set-Cookie attributes like Path, Domain, Max-Age, Secure, HttpOnly, and SameSite:

    ///|
    test "parse cookie with attributes" {
    let cookies = @cookie.parse_cookie(
    "token=xyz; Path=/api; Secure; HttpOnly; SameSite=Strict",
    )
    guard cookies.get("token") is Some(c) else { fail("expected token cookie") }
    assert_eq(c.path, Some("/api"))
    assert_eq(c.secure, Some(true))
    assert_eq(c.http_only, Some(true))
    assert_eq(c.same_site, Some(Strict))
    }

    #Serializing Multiple Cookies

    cookie_to_string joins an array of cookies into a semicolon-separated string:

    ///|
    test "serialize multiple cookies" {
    let cookies = [
    @cookie.CookieItem(name="a", value="1"),
    CookieItem(name="b", value="2"),
    ]
    debug_inspect(
    @cookie.cookie_to_string(cookies),
    content=(
    #|"a=1;b=2"
    ),
    )
    }

    #SameSite Options

    The SameSiteOption enum controls cross-site request behavior:

    VariantMeaning
    LaxSent on top-level navigations and GET requests
    StrictSent only on same-site requests
    SameSiteNoneSent on all requests (requires Secure)

    CookieItem

    pub(all) struct CookieItem {
    name : String
    value : String
    max_age : Int?
    path : String?
    domain : String?
    secure : Bool?
    http_only : Bool?
    same_site : SameSiteOption?
    } derive(Eq,
    Debug
    )

    Represents an HTTP cookie with its name, value, and optional attributes.
    impl Show for CookieItem

    CookieItem::CookieItem

    fn CookieItem::CookieItem(name~ : String, value~ : String, max_age? : Int, path? : String, domain? : String, secure? : Bool, http_only? : Bool, same_site? : SameSiteOption) -> CookieItem

    Creates a new CookieItem with the given name, value, and optional attributes.

    CookieItem::equal

    fn CookieItem::equal(CookieItem, CookieItem) -> Bool

    CookieItem::not_equal

    fn CookieItem::not_equal(x : CookieItem, y : CookieItem) -> Bool

    CookieItem::output

    fn CookieItem::output(self : CookieItem, logger : &Logger) -> Unit

    CookieItem::to_string

    fn CookieItem::to_string(self : CookieItem) -> String

    SameSiteOption

    pub(all) enum SameSiteOption {
    Lax
    Strict
    SameSiteNone
    } derive(Eq,
    Debug
    )

    The SameSite attribute for cookies, controlling cross-site request behavior.

    SameSiteOption::equal

    SameSiteOption::not_equal

    fn SameSiteOption::not_equal(x : SameSiteOption, y : SameSiteOption) -> Bool

    SameSiteOption::output

    fn SameSiteOption::output(self : SameSiteOption, logger : &Logger) -> Unit

    SameSiteOption::to_json

    fn SameSiteOption::to_json(self : SameSiteOption) -> Json

    SameSiteOption::to_string

    fn SameSiteOption::to_string(self : SameSiteOption) -> String

    fn cookie_to_string(cookie : Array[CookieItem]) -> String

    Serializes an array of cookie items into a semicolon-separated string.
    fn parse_cookie(cookie : StringView) -> Map[String, CookieItem]

    Parses a raw cookie header string into a map of cookie names to CookieItem values.

    Source Files