Cookie::Jar
NAME
Cookie::Jar - A minimalist HTTP user agent cookie jar
SYNOPSIS
use Cookie::Jar;
my $cookies = Cookie::Jar.new;
$cookies.add: 'https://example.com', 'foo=123; Domain=example.com';
$cookies.add: 'https://example.com', 'bar=234';
say "{ .name } -> { .value }" for $cookies.get: 'GET', 'https://example.com';
# OUTPUT:
# foo -> 123
# bar -> 234
# The 'bar' cookie does not apply to this subdomain
say $cookies.header: 'GET', 'https://www.example.com';
# OUTPUT:
# foo=123
# Cookies can persist on filesystem
my $other = $jar.save('cookie.jar').load('cookie.jar');
DESCRIPTION
This is a minimal class to manage HTTP cookies. It can be used together with a HTTP client class like HTTP::Tiny to manage cookies received in HTTP responses and determine the cookies that apply on new requests.
Unlike other alternatives available at the time of writing, user agents desiring to integrate with this class do not need to use a specific class to represent the request, the response, or the cookie: all that is required is the request URL and the headers received from the server.
The operations on this library should be thread-safe.
METHODS
Some of the methods below take a request URL parameter. In compliance with RFC 6265, these are all canonicalised to their ASCII "punycode" representation before processing.
Likewise, the methods in this class that return cookies (like get and dump described below) return a read-only opaque cookie object with the following available methods:
The Cookie Object
creation-time
A DateTime marking the moment the cookie was created. This could be before the jar was created if the cookie was loaded from external storage with load. This attribute is internal, and does not conflict with an extension of the same name.
domain
Returns a Str with the cookie's domain. If the cookie did not have a domain initially, this will be the domain the cookie was received from.
expired
Returns a Bool that will be true if the cookie is persistent and its expiration date is in the past. It can optionally take a DateTime object to be used instead of the current timestamp.
expires
Returns a DateTime with the cookie's expiration time. This might be a type object if the cookie is not persistent.
host-only
Returns a Bool specifying whether the cookie should apply to domains other
than the one in its "domain" attribute. This attribute can also be called as
hostonly
.
http-only
Returns a Bool specifying whether this cookie should be included in non-HTTP
requests (this is of little use for Raku user-agents). This attribute can
also be called as http-only
.
last-access-time
Returns a DateTime specifying when the cookie was last matched for a given URL (using the get or header methods). This attribute is internal, and does not conflict with an extension of the same name.
name
Returns a Str with the cookie name. This attribute is internal, and does not conflict with an extension of the same name.
path
Returns a Str with the path the cookie applies to.
persistent
Returns a Bool which will be true if the cookie has a defined expiration date.
secure
Returns a Bool specifying whether this cookie should be sent over non-secure channels. Cookies with this attribute set to a true value will only be matched for HTTPS requests.
value
Returns a Str with the value of the cookie. No effort is made by Cookie::Jar to parse or otherwise decode this value. This attribute is internal, and does not conflict with an extension of the same name.
get
Takes a key that will be matched case-insensitively to a cookie attribute. The key can be any of the ones mentioned above, or the name of any of the cookie's extensions. If the cookie does not have an attribute with that name this method will return False. Otherwise, the value of the attribute will be returned, or True if the attribute has no value. If the cookie was set with an attribute with the same name as one of the fields described as "internal" above (eg. 'creation-time' and 'last-access-time', etc), using that key with this method will return the extension.
new
method new () returns Cookie::Jar
Creates a new Cookie::Jar object. The constructor takes no parameters.
To construct a Cookie::Jar with cookies that have been saved on a previous session (with the save method), see the load method below.
add
method add (
Str:D $url,
Str:D $cookie-string,
) returns Bool
Add a new cookie to the internal storage.
This method takes a URL and a Set-Cookie
header string (received from making
a request to that URL) and adds the cookie to the jar. If the cookie is
expired, any matching cookie is deleted as described in RFC 6265 § 4.1.2.
If the PublicSuffix module is available, it will be used to validate cookie domains and reject supercookies.
Returns True if the cookie was successfully added, or False otherwise.
dump
method dump () returns Hash
This method offers some introspection by returns a Hash representation of the internal storage used by the jar.
The data structure store cookies indexed by nested domain, path, and cookie name keys, as in the following example:
{
'example.com' => {
'/path' => {
'SID' => ..., # see below for details on cookie values
}
},
}
Cookies in this structure (the parts represented by the ellipsis) will be returned as an internal read-only Cookie object. For details on this Cookie object, see above.
get
method get (
Str:D $method,
Str:D $url,
) returns List
Takes a request method and URL and returns a (possibly empty) list of cookies
that would apply to a request made to that URL, as described in
RFC 6265 § 5.4. The order of the cookies in the list follows the same order
they would take in a Cookie
header sent with that request, as per the
document above.
The method must be one of CONNECT
, DELETE
, GET
, HEAD
, OPTIONS
,
PATCH
, POST
, PUT
, or TRACE
, and will be matched case-sensitively, as
per HTTP/1.1 specification.
Elements in the list will be internal read-only Cookie objects. For details on this Cookie object, see above.
header
method header (
Str:D $method,
Str:D $url,
) returns Str
Takes a request method and URL and returns a (possibly empty) string suitable
to be used as the Cookie
header sent to a request made to that URL. The
order of the cookies in the string follows the order described in
RFC 6265 § 5.4.
The method must be one of CONNECT
, DELETE
, GET
, HEAD
, OPTIONS
,
PATCH
, POST
, PUT
, or TRACE
, and will be matched case-sensitively, as
per HTTP/1.1 specification.
This method calls get internally.
clear
multi method clear ( ) returns Cookie::Jar
multi method clear (
Str $url,
*@names,
) returns Cookie::Jar
Clear the internal storage of the jar.
When called with no arguments, all values will be deleted.
This method can alternatively be called with a URL and a possibly empty list of cookie names. In this case cookies that would match a request made to that URL (as per the same rules used by the get method), and possibly one of the names provided, then those matching cookies will be deleted.
save
method save (
IO() $path,
) returns Cookie::Jar
Save the internal storage into a cookie file. This file will is suitable to be read with the load method below. Only persistent cookies will be saved.
This method returns the calling object.
load
method load (
IO() $path,
) returns Cookie::Jar
Load cookies from a cookie file, like that generated with save.
If called on an existing instance, the internal storage will be cleared before reading the input file. This method can also be called on a Cookie::Jar type object to be used as a constructor.
In both cases, this method will return a Cookie::Jar object with the cookies loaded from the read file.
LIMITATIONS
Cookie::Jar aims to be conditionally compliant with the HTTP State Management Mechanism RFC 6265.
It aims to meet all "MUST" requirements of the specification, but only some of the "SHOULD" requirements.
Some particular limitations of note include:
Cookie::Jar cannot currently be configured to reject public suffixes as described in RFC 6265 § 5.3.
Cookie::Jar does no support features that were obsoleted by RFC 6265. This includes the
Cookie2
andSet-Cookie2
headers,.local
suffixes, etc.Since RFC 6265 is the only current specification of HTTP cookie behaviour, Cookie::Jar does not support features that are not described in it. This includes features like SameSite.
SEE ALSO
Other cookie jars
Cro::HTTP::Client::CookieJar
Shipped as part of Cro::HTTP and is used by that client. The client cannot be configured to use another cookie jar.
HTTP::Cookies
Shipped as part of HTTP::UserAgent and is used by that client. The client cannot be configured to use another cookie jar.
Additional Features
Cookie::Baker
Cookie::Baker provides two functions, one of which, bake-cookie
, can be
used to convert a Hash into a string that can be used as a Cookie
header.
This can be used together with the add method to add a cookie from a
set of key-value pairs.
PublicSuffix
If this distribution is installed, Cookie::Jar will use it to verify cookie domains against the list of public suffixes, as described in step 5 of RFC 6265 § 5.3. This should help avoid supercookies.
AUTHOR
José Joaquín Atria [email protected]
ACKNOWLEDGEMENTS
Other than the cookie jars mentioned above, the code and API in this distribution takes inspiration from a number of similar Perl libraries. In particular:
This module owes a debt of gratitude to their authors and those who have contributed to them, and to their choice to make their code and work publicly available.
COPYRIGHT AND LICENSE
Copyright 2022 José Joaquín Atria
This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.