Yaws and Cookies

Cookies are the means in HTTP to assign data to a session. A HTTP session typically consists of many (and sometimes concurrent) TCP connections from the client to the web server. The first time a client arrives to our webserver, we issue the HTTP header Set-Cookie: var=someval. The browser will then in subsequent connections to the same server pass this cookie "var=someval" in its client side Cookie: var=someval header. We can thereby assign state to a session, either through data actualy encoded into the cookie value itself, or by associating server side session data to the cookie.

Let's do an example where we set a simple cookie, and create a specific erlang process which is then responsible for that session. The cookie value will be a string encoding of the pid handling the session.

The yaws code in setcookie.yaws sets the cookie in the browser. Note that the call to yaws_api:set_cookie/3 in the example returns a header setting (like {header, HeaderNameAndValue}) from the out/1 function, which directs Yaws to set the specified header in the response to the browser.

And the yaws code in readcookie.yaws will read the cookie and report some uninteresting session data.

A correct definition of cookies can be found in RFC 6265

Set Cookie

The code to set the cookie looks like:


session(A, Visits) ->
    receive
        {From, tick} ->
            N = calendar:local_time(),
            From ! {self(), [N|Visits]},
            session(A, [N|Visits])
    after 60000 ->    %% keep state for 60 secs only
            exit(normal)
    end.

out(A) ->
    H = A#arg.headers,
    C = H#headers.cookie,
    case yaws_api:find_cookie_val("foobar", C) of
        [] ->
            Now = calendar:local_time(),
            P = spawn(fun() -> session(A, [Now]) end),
            yaws_api:set_cookie("foobar",
                                pid_to_list(P), [{path,"/"}]);
        PidStr ->
            Pid = list_to_pid(PidStr),
            case process_info(Pid, messages) of
                undefined ->
                    Now = calendar:local_time(),
                    P = spawn(fun() ->
                                      session(A, [Now])
                              end),
                    yaws_api:set_cookie("foobar",
                                        pid_to_list(P),
                                        [{path,"/"}]);
                _ ->
                    ok
            end
    end.

This is the page that set the cookie in the browser. readcookie.yaws will read the cookie and report persistent information as long as the browser session exists.

it will set the cookie foobar = <x,y,z>; where the x,y,z string is the textual representation of an actual erlang pid which will be responsible for this session.

Valid XHTML 1.0!