Sunday 9 November 2014

Plack::Test and Dancer Session

PSGI is very easy to understand: a black box, something goes in, something goes out. What goes in: a request made of a path and headers. What goes out: a response with a content and more headers.

Plack::Test follows this structure. What you have to test is the black box, you inject the request in it and analyze the response you receive back.

Important thing to understand is that Plack::Test is something very different from an emulation of a browser like LWP::UserAgent. Most important difference is, obviously, in session management, because that's something that should survive between calls and in Plack::test every call is a test by itself, with no memory of what happens around it.

What do you have to do  if you want to test something like a login using Plack::Test? Well, the solution is very easy because the concept of session is AN ILLUSION throughout all the web. It's not just Plack::Test, the HTTP protocol itself is session-less. The "session" you see is just a set of tricks that clients and servers do under the hood.

As we said: a request go, a response returns, nothing more, so the session is something that must be hidden there. In particular, session is controlled throught headers, in particular headers that control browser cookies.

There're a lot of documentation about how cookies and response headers have to interact and probably studying it could be very interesting, but HTTP::Cookies module contains all the knowledge you need so learn to use it will be enough.

Let's do a login and get the response from it:

$r = $cb->( POST '/admin/login', [ user => 'admin', password => 'admin' ] );

Response object $r contain many headers, one of that ask the client to write in a cookie the identifier of dancer session. We can use HTTP::Cookies to extract this information.

my $jar = HTTP::Cookies->new;
$jar->extract_cookies($r);

Now we want that, in the next call, the server find us logged in.

When a browser does a request to a site, it passes in the request all the informations related to the cookies it has. This way it can say to the server what is its dances session identifier. Using that, the server can retrieve any information about the caller, like its status as logged user.

Let's cook a call for admin homepage.

my $req = HTTP::Request->new(GET => $site . '/admin');

WARNING: Remember to ALWAYS create request with complete URL, starting from http, otherwise HTTP::Cookies method add_cookie_header will not work!

Now we want that this call carry information about the cookies of the previous call, where logged in user session was configured. We just have to get information out from the cookie jar.

$jar->add_cookie_header($req);

Now this req will been seen by the server as the logged user from the previous call did it.

Well, if you configured in a clever way the server too.

Remember? There's no memory between requests client-side AS server-side. Client memory is in the cookies and HTTP::Cookies helps us to manage it. Where is server memory?

Standard session management in Dancer leave session information in RAM. On a development server this is enough, but a development server is something that stay alive between different calls so you can consider information stored in RAM persistent. Plack::Test instantiate the black box fresh new at every call so information about sessions is always trashed at the end of it.

Harddisk is more reliable if you want to store persisten information so switch session management to YAML when doing this kind of test.

Here is a little example of what we said.



No comments:

Post a Comment