NAME

PAGI::Middleware::Session - Session management middleware

SYNOPSIS

use PAGI::Middleware::Builder;

my $app = builder {
    enable 'Session',
        secret => 'your-secret-key',
        cookie_name => 'session_id';
    $my_app;
};

# In your app:
async sub app {
    my ($scope, $receive, $send) = @_;

    my $session = $scope->{'pagi.session'};
    $session->{user_id} = 123;
    $session->{logged_in} = 1;
}

DESCRIPTION

PAGI::Middleware::Session provides server-side session management with cookie-based session IDs. Sessions are stored in memory by default.

Warning: The default in-memory store is suitable for development and single-process deployments only. Sessions are not shared between workers and are lost on restart. For production multi-worker deployments, provide a store object backed by Redis, a database, or another shared storage.

CONFIGURATION

  • secret (required)

    Secret key for session ID generation and validation.

  • cookie_name (default: 'pagi_session')

    Name of the session cookie.

  • cookie_options (default: { httponly => 1, path => '/' })

    Options for the session cookie.

  • expire (default: 3600)

    Session expiration time in seconds.

  • store (default: in-memory hash)

    Session store object for production use. Must implement get($id), set($id, $data), delete($id). See warning above about the default in-memory store.

CUSTOM STORES

For production multi-worker deployments, implement a store class with three methods. Here's a Redis example:

package MyApp::Session::Redis;
use Redis;
use JSON::MaybeXS qw(encode_json decode_json);

sub new {
    my ($class, %opts) = @_;
    return bless {
        redis  => Redis->new(server => $opts{server} // '127.0.0.1:6379'),
        prefix => $opts{prefix} // 'session:',
        expire => $opts{expire} // 3600,
    }, $class;
}

sub get {
    my ($self, $id) = @_;
    my $data = $self->{redis}->get($self->{prefix} . $id);
    return $data ? decode_json($data) : undef;
}

sub set {
    my ($self, $id, $session) = @_;
    my $key = $self->{prefix} . $id;
    $self->{redis}->setex($key, $self->{expire}, encode_json($session));
}

sub delete {
    my ($self, $id) = @_;
    $self->{redis}->del($self->{prefix} . $id);
}

1;

Then use it:

enable 'Session',
    secret => $ENV{SESSION_SECRET},
    store  => MyApp::Session::Redis->new(
        server => 'redis.example.com:6379',
        expire => 7200,
    );

SCOPE EXTENSIONS

This middleware adds the following to $scope:

  • pagi.session

    Hashref of session data. Modify this directly to update the session. Keys starting with _ are reserved for internal use.

  • pagi.session_id

    The session ID string.

SESSION DATA

Special session keys:

  • _id - Session ID (read-only)

  • _created - Unix timestamp when session was created

  • _last_access - Unix timestamp of last access

  • _regenerated - Set to 1 to regenerate session ID

SEE ALSO

PAGI::Middleware - Base class for middleware

PAGI::Middleware::Cookie - Cookie parsing