Rand Stats

Cro::HTTP::Session::SQLite

zef:demayl

cro-http-session-sqlite

Cro::HTTP::Session::SQLite

NAME

Cro::HTTP::Session::SQLite - An implementation of Cro persistent sessions using SQLite.

SYNOPSIS

use Cro::HTTP::Session::SQLite;

DESCRIPTION

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.

INSTALLATION

zef install Cro::HTTP::Session::SQLite

FUNCTIONALITY

Database default setup

CREATE TABLE IF NOT EXISTS sessions (
	id varchar(255), 
	state json,
	ip_addr varchar(255),
	user_id INTEGER,
	expiration TIMESTAMP,
	created TIMESTAMP DEFAULT CURRENT_TIMESTAMP 
);
CREATE INDEX session_id ON sessions (id);
CREATE INDEX expired_date ON sessions (expiration);

Minimal Cro application setup

class MySession {
    has $.user-id;
	has $.ip-addr;

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

my $application = route {

    before Cro::HTTP::Session::SQLite[UserSession].new();

    get -> UserSession $user {
        $user.user-id = 123;
		$user.ip-addr = '127.0.0.1';
        content 'text/plain', "Hello, TEST!";
    }
}

my Cro::Service $hello = Cro::HTTP::Server.new:
    :host<localhost>, :port(80), :$application;

Here are the keypoints here:

Custom setup

before Cro::HTTP::Session::SQLite[UserSession].new( 
	expiration => Duration.new(60 * 60), # 60 minutes expiration
	cookie-name => 'CustomCookieName',
	db-path => '/home/user/app/sessions.db',
	restrict-ip-addr => True,
	autoclean-every-seconds => 60, # Cleanup the sessions table every 60 seconds
	key => ("0" x 32).encode, - Encryption key
	iv => ("0" x 16).encode, - Encryption IV
	skip-cookie => -> Cro::HTTP::Response $response { # Skip the cookie if the request is application/json
		my $content-type = $response.request.header('content-type');
		$content-type && $content-type eq 'application/json'
		}
	);

Here we have a custom setup:

For full setup see the constructor below

Constructor

All fields are optional

DBDish::SQLite::Connection $.db

DBIish connection. Default auto connects

IO::Path $.db-path

Path to the DB SQLite3 file. Default ./sessions.db

Str $.cookie-name

Name of the cookie. Default CroCookie

Duration $.expiration

Expiration duration for the cookie. Default Duration.new( 30*60 )

Int $.autoclean-every-seconds

Session cleanup every X seconds. Default 1800

Str $.sessions-table

Name of the DB table. Default sessions

Str $.id-column

Name of the ID column in the DB. Default id

Str $.state-column

Name of the state column in the DB. Default state

Str $.expiration-column

Name Of the expiration column. Default expiration

Str $.ip-addr-column

Name of the IP address column. Default ip_addr

Str $.user-id-column

Name of the User ID column. Default user_id

Str $.created-column

Name of the Created column. Default created

Str $.ip-addr-field

Field name from your Session object, that is used to store the IP address in the table column $.ip-addr-column. Default ip-addr

Str $.user-id-field

Field name from your Session object, that is used to store the User ID in the table column $.user-id-column. Default user-id

Bool $.restrict-ip-addr

IP cookie bind. Looksup the $.ip-addr-field from your Session object. Default True

Callable &.skip-cookie

Custom function that can disable the session. Default Nil

Buf() $.key

Encryption key. See OpenSSL for more information

Buf() $.iv

IV. See OpenSSL for more information

Controlling serialized data

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

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

AUTHOR

Denis Kanchev

COPYRIGHT AND LICENSE

Copyright 2025 Denis Kanchev

This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.