txt: ## dist_zef-jjatria-Cookie-Jar.md
  # NAME
  
  Cookie::Jar - A minimalist HTTP 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](https://raku.land/zef:jjatria/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](https://datatracker.ietf.org/doc/html/rfc6265), these are all canonicalised to their ASCII "punycode"
  representation before processing.
  
  Likewise, the methods in this class that return cookies (like [get](#get) and
  [dump](#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](#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 `httponly`.
  
  **last-access-time**
  
  Returns a DateTime specifying when the cookie was last matched for a given
  URL (using the [get](#get) or [header](#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](#save) method), see the [load](#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](https://datatracker.ietf.org/doc/html/rfc6265#section-4.1.2).
  
  If the [PublicSuffix](https://raku.land/zef:jjatria/PublicSuffix) module is available, it will be used to validate cookie
  domains and reject [supercookies](https://en.wikipedia.org/wiki/HTTP_cookie#Supercookie).
  
  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](#the-cookie-object).
  
  ### 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](https://datatracker.ietf.org/doc/html/rfc6265#section-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](#the-cookie-object).
  
  ### 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](https://datatracker.ietf.org/doc/html/rfc6265#section-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](#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](#get) method), and possibly one
  of the names provided, then those matching cookies will be deleted.
  
  ### save
  
  ```
  method save (
      IO()    $path,
      Bool() :$netscape,
      Bool() :$all,
  ) returns Cookie::Jar
  
  ```
  
  Save the internal storage into a cookie file. This file will is suitable to be
  read with the [load](#load) method below. Only persistent cookies will be saved,
  unless the `:all` flag is set to a true value.
  
  By default, the file will be written using an internal format used by
  Cookie::Jar. If the `:netscape` flag is set to a true value, the file will
  instead use the [Netscape HTTP Cookie File](https://curl.haxx.se/docs/http-cookies.html) format, compatible with those
  created by `libcurl`.
  
  This method returns the calling object.
  
  ### load
  
  ```
  method load (
      IO()    $path,
      Bool() :$netscape,
  ) returns Cookie::Jar
  
  ```
  
  Load cookies from a cookie file, like that generated with [save](#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.
  
  By default, the file is assumed to use the internal Cookie::Jar format.
  If the file is found to have a [Netscape HTTP Cookie File](https://curl.haxx.se/docs/http-cookies.html) header instead
  (like the one generated by `libcurl`), the file will be parsed as such.
  Setting the `:netscape` flag to a true value enforces this, such that
  providing a file missing this header is an error.
  
  # LIMITATIONS
  
  Cookie::Jar aims to be *conditionally compliant* with the HTTP State
  Management Mechanism [RFC 6265](https://datatracker.ietf.org/doc/html/rfc6265).
  
  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 does no support features that were obsoleted by [RFC 6265](https://datatracker.ietf.org/doc/html/rfc6265).
    This includes the `Cookie2` and `Set-Cookie2` headers, `.local` suffixes,
    etc.
  * Since [RFC 6265](https://datatracker.ietf.org/doc/html/rfc6265) 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](https://raku.land/cpan:JNTHN/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](https://raku.land/github:sergot/HTTP::UserAgent) and is used by that client. The client
  cannot be configured to use another cookie jar.
  
  ### Additional Features
  
  #### [Cookie::Baker](https://raku.land/github:tokuhirom/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](#add) method to add a cookie from a
  set of key-value pairs.
  
  #### [PublicSuffix](https://raku.land/zef:jjatria/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](https://datatracker.ietf.org/doc/html/rfc6265#section-5.3). This should help avoid [supercookies](https://en.wikipedia.org/wiki/HTTP_cookie#Supercookie).
  
  # AUTHOR
  
  José Joaquín Atria [jjatria@cpan.org](mailto:jjatria@cpan.org)
  
  # 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:
  
  * [HTTP::CookieJar](https://metacpan.org/pod/HTTP::CookieJar)
  * [HTTP::Cookies](https://metacpan.org/pod/HTTP::Cookies)
  * [Mojo::UserAgent::CookieJar](https://metacpan.org/pod/Mojo::UserAgent::CookieJar)
  
  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.
  