Rand Stats

The uploading author of cpan:JNTHN does not match the META author of Edument.

Cro::HTTP::Session::Pg

cpan:JNTHN

Cro::HTTP::Session::Pg

An implementation of Cro persistent sessions using Postgres.

Assumptions

There are dozens of ways we might do session storage; this module handles the case where:

If these don't meet your needs, it's best to steal the code from this module into your own application and edit it as needed.

Database setup

Create a table like this in the database:

CREATE TABLE sessions (
    id TEXT PRIMARY KEY,
    state TEXT,
    expiration TIMESTAMP
);

You can change the table and column names, but will then have to specify them when constructing the session state object.

Minimal Cro application setup

First, create a session object if you do not already have one. This is a class that holds the session state. We'll be saving/loading its content. For example:

class MySession {
    has $.user-id;

    method set-logged-in-user($!user-id --> Nil) { }

    method is-logged-in(--> Bool) { $!user-id.defined }
}

In the case that:

Then the only thing needed is to construct the session storage middleware with a database handle and a session cookie name.

my $session-middleware = Cro::HTTP::Session::Pg[MySession].new:
    :$db,
    :cookie-name('my_app_name_session');

It can then be applied as application or route-block level middleware.

Tweaking the session duration

Pass a Duration object as the duration named argument:

my $session-middleware = Cro::HTTP::Session::Pg[MySession].new:
    :$db,
    :cookie-name('my_app_name_session'),
    :duration(Duration.new(15 #`(minutes) * 60)); 

Tweaking the table and column names

Pass these named arguments as needed during construction:

Controlling serialization

Instead of using the Cro::HTTP::Session::Pg role directly, create a class that composes it.

class MySessionStore does Cro::HTTP::Session::Pg[MySession] {
    method serialize(MySession $s) {
        # Replace this with your serialization logic.
        to-json $s.Capture.hash
    }
    
    method deserialize($d --> MySession) {
        # Replace this with your deserialization logic.
        Session.new(|from-json($d))
    }
}