Next: , Previous: , Up: Top   [Contents][Index]


11 (www server-utils cookies)

Cookies are bits of client-side state the server can maintain through designated HTTP response headers. At this time (2009), there are two specifications, RFC21091 and RFC29652, the latter obsoleting the former.

This chapter describes the (www server-utils cookies) module, which provides facilities for creating such headers, and parsing those sent by the client. Procedures that return trees are meant to be used with the mouthpiece command #:add-header (see answer).

Procedure: simple-parse-cookies string [sep]

Parse string for “cookie-like fragments”, that is, zero or more substrings of the form name=value, separated by character sep and optionally trailing whitespace. By default, sep is #\, (comma).

Return a list of elements (name . value), where both name and value are strings. For example:

(define COOKIE "abc=def; z=z, ans=\"42\", abc=xyz")

(simple-parse-cookies COOKIE)
⇒ (("abc" . "def; z=z") ("ans" . "\"42\"") ("abc" . "xyz"))

(simple-parse-cookies COOKIE #\;)
⇒ (("abc" . "def") ("z" . "z, ans=\"42\", abc=xyz"))
Procedure: rfc2109-set-cookie-string name value [keyword value…]
Keywords: path, domain, expires, secure 

Return a string suitable for inclusion into an HTTP response header as a cookie with name and value. Both args may be strings, symbols or keywords. Also, recognize and format appropriately the optional keyword parameters #:path, #:domain, #:expires (strings); and #:secure (boolean).

Procedure: rfc2965-set-cookie2-tree M [cookie-specs…]

Compute a list suitable for inclusion in an HTTP response header, composed by formatting cookie-specs, each a list of the form (name value a1 v1…). Each name may be a string, symbol or keyword. Each value may be a string or symbol. Each a must be a keyword, precisely one of:

#:Comment  #:CommentURL  #:Discard  #:Domain
#:Max-Age  #:Path  #:Port  #:Secure

The #:Version attribute is automatically included as the last one; it cannot be specified (or de-specified).

Possible values for v depend on a. If a is #:Discard or #:Secure, then there is no v (it must be omitted). If a is #:Port, then v must be either a number; a list of numbers, for instance (8001 8002 8003); or omitted entirely. If a is #:Max-Age, then v must be a number. For all other a, v can be a string or symbol.

If M is #f, return a list. The CAR of the list is the keyword #:Set-Cookie2, and the CDR is a tree of strings. Otherwise M should be a mouthpiece (see answer) in which case it is applied with the #:add-header command to the list.

example

Here is an example that demonstates both RFC2109 and RFC2965 formatting. Notable differences: the keyword to specify the path is now capitalized; the representation of the cookie’s value is now double-quoted.

;; RFC2109
(rfc2109-set-cookie-string 'war 'lose #:path "/ignorance/suffering")
⇒ "Set-Cookie: war=lose; path=/ignorance/suffering"

;; RFC2965
(use-modules ((www server-utils answer) #:select (walk-tree)))

(define TREE (rfc2965-set-cookie2-tree
              '(war lose #:Path "/ignorance/suffering" #:Discard)))

(car TREE)
⇒ #:Set-Cookie2

(walk-tree display (cdr TREE))
-| war="lose";Path="/ignorance/suffering";Discard;Version=1

To generate a cookie spec from the Cookie http response header sent by a client, you can use rfc2965-parse-cookie-header-value.

Procedure: rfc2965-parse-cookie-header-value s [flags…]

Parse the Cookie HTTP response header string s. Return a list of the form (vers n [cookie-spec…]), where vers is the version number of the cookie specification, 0 (zero) for RFC2109 compliance and 1 (one) for RFC2965 compliance; and n is the number of cookie-specs the CDR of the form.

Each cookie-spec has the form: (name value a1 v1…). name, value are strings. Each a is a keyword, one of #:Path, #:Domain or #:Port. Each v is a string, except for that associated with #:Port, which is can be either a single number or a list of numbers.

Optional flags configure the parsing and/or return value.

#:keep-attribute-dollarsign-prefix

Prevent conversion of, for example, #:$Port to #:Port.

#:strict-comma-separator

Disable support for older clients that use a semicolon to separate cookies instead of a comma. Normally, parsing copes (heuristically) with this by reparsing an unrecognized attribute as the beginning of a new cookie. With this flag, an unrecognized attribute signals an error.

#:canonicalize-NAME-as-keyword

Convert the name in each cookie-spec into a keyword whose first character and characters following a hyphen are upcased. For example, "session-id-no" would become #:Session-Id-No.

Parsing may signal an error and display an error message in the form: “situation while context”, where situation is one of “unexpected end”, “missing equal-sign”, “bad attribute”, or “missing semicolon”; and context is one of: “reading string”, “reading token”, “reading pair”, “reading one cookie” or “parsing”. The error message also displays string s on a line by itself and on the next line a caret by itself indented to be at (or near) the site of the error.

RFC2965 also specifies some other small algorithms, some of which are codified as procedures available in this module.

Procedure: reach h

Return the reach (a string) of host name h. Quoting from RFC2965 section 1 (Terminology):

The reach R of a host name H is defined as follows:
If
  - H is the host domain name of a host; and,
  - H has the form A.B; and
  - A has no embedded (that is, interior) dots; and
  - B has at least one embedded dot, or B is the string "local".
then the reach of H is .B.
Otherwise, the reach of H is H.

Note that comparison with "local" uses string=?, i.e., case-sensitively.


Footnotes

(1)

RFC2109

(2)

RFC2965


Next: , Previous: , Up: Top   [Contents][Index]