Skip to content

Latest commit

 

History

History
103 lines (74 loc) · 2.58 KB

README.md

File metadata and controls

103 lines (74 loc) · 2.58 KB

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:

  • The database is being accessed using DB::Pg.
  • You're fine with the session state being serialized and stored as a string/blob in the database.

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:

  • You are using the default table/column names
  • Your session object can be serialized by serializing its public attributes to JSON, and deserialized by passing those back to new
  • You are fine with the default 60 minute session expiration time

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:

  • sessions-table
  • id-column
  • state-column
  • expiration-column

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))
    }
}