Araneida - Cookies

Araneida - How To Work With Cookies

# Cookies

To store data client-side, put it in a cookie. Cookies have a name and a value. There are some restrictions on what the name can be: stick with just alphabet characters and you'll be okay.

First, you have to send the cookie to the client:

    (defmethod handle-request-response ((handler intro-handler) method request)
      (request-send-headers request :set-cookie (cookie-string "cookiename" "cookievalue"))
      (html-stream
       (request-stream request)
       `(html (body
               (p "Cookie set.")))))

Afterwards, this cookie value will be available via a call to REQUEST-COOKIE.

    (defmethod handle-request-response ((handler show-cookie) method request)
      (request-send-headers request)
      (html-stream
       (request-stream request)
       `(html (body
    	   (p "The cookie value is: " ,(request-cookie request "cookiename"))))))

To set a new value for the cookie, re-send the cookie as above.

There are more parameters to cookie-string than shown here, they are all keyword parameters. To have the above be a session cookie (deleted when the browser is closed):

    (cookie-string "cookiename" "cookievalue" :max-age 0)

To see the full parameter list:

    (documentation 'cookie1:cookie-string 'function)

# Prevent Cookie Spoofing

It is possible for another website to send your site a cookie without you being aware of it. If dan.example.com set a cookie like so:

    (cookie-string "bad" "cookie" :domain ".example.com")

and your website was ann.example.com, you would receive that cookie.

If your web app does not use domain cookies, it's best to ignore them - which would ignore the above cookie.

    (request-safe-cookie request "my" nil)

If you do use domain cookies, it's best to specify the domains you will accept explicitly.

    (request-safe-cookie request "my" ".example.com")

This will not stop all instances, but it's a good start.

# When the cookie isn't found

When you request a specific cookie, there is the possibility that it won't be found. Sometimes it's easier to assume the cookie is found, and set up a signal handler for when it isn't.

The REQUEST-COOKIE and REQUEST-SAFE-COOKIE methods take a keyword parameter that can enable signaling an error.

    (handler-case
        (request-cookie request "mycookie" :on-fail :signal-condition)
      (cookie-not-found (condition) (format *trace-output* "Cookie not found! ~A" condition)))

By default the methods return nil.