Cookie

One small class to read, write and delete HTTP cookies, with the sharp edges filed off.

Bake a cookie and watch the header →

The three operations

use Cookie;

# READ — parse the incoming Cookie: header (defaults to $ENV{HTTP_COOKIE})
my %jar = Cookie->read;
my $sid = Cookie->get('session');

# WRITE — build and emit a Set-Cookie: header
my $c = Cookie->new(
    name     => 'session',
    value    => 'abc 123/=?',      # URL-encoded automatically
    expires  => '+7d',             # epoch | +7d | +30m | +12h | now | session
    secure   => 1,
    samesite => 'Lax',             # HttpOnly + SameSite=Lax on by default
);
print $c->header, "\r\n";

# DELETE — expire it, matching the Path/Domain it was set with
print Cookie->new( name => 'session', path => '/' )->delete, "\r\n";

Why not just interpolate a string

Because cookie values are attacker-adjacent and the header is line-oriented.

neutralises ;, CR, LF and the RFC separators while still round-tripping. A raw => 1 value is still screened for header-breaking bytes.

separators.

or a semicolon is rejected rather than emitted.

Secure, Path=/ and no Domain. The class makes those true instead of trusting you to remember.

otherwise.

Expiry

expires accepts an epoch, a relative offset (+7d, +30m, +12h, +1y), now, or session. Max-Age is emitted alongside Expires for older clients, and the date is formatted locale-independently — a LANG change cannot produce an unparseable cookie date.

In this site

Loom's admin session cookie and Tally's visitor cookie are both plain Set-Cookie headers built on these rules. The demo page lets you set attributes yourself and shows the exact bytes that go on the wire.