NAME
PAGI::Runner - PAGI application loader and server runner
SYNOPSIS
# Command line usage via pagi-server
pagi-server PAGI::App::Directory root=/var/www
pagi-server ./app.pl -p 8080
pagi-server # serves current directory
# Programmatic usage
use PAGI::Runner;
my $runner = PAGI::Runner->new;
$runner->parse_options(@ARGV);
$runner->run;
# Or all-in-one
PAGI::Runner->new->run(@ARGV);
# For testing
my $runner = PAGI::Runner->new(port => 0, quiet => 1);
$runner->load_app('PAGI::App::Directory', root => '.');
my $server = $runner->prepare_server;
DESCRIPTION
PAGI::Runner is a loader and runner for PAGI applications, similar to Plack::Runner for PSGI. It handles CLI argument parsing, app loading (from files or modules), and server orchestration.
APP LOADING
The runner supports three ways to specify an application:
Module Name
If the app specifier contains ::, it's treated as a module name:
pagi-server PAGI::App::Directory root=/var/www show_hidden=1
The module is loaded, instantiated with the provided key=value arguments, and to_app is called to get the PAGI app coderef.
File Path
If the app specifier contains / or ends with .pl or .psgi, it's treated as a file path:
pagi-server ./app.pl
pagi-server /path/to/myapp.psgi
The file is loaded via do and must return a coderef.
Default
If no app is specified, defaults to serving the current directory:
pagi-server # same as: PAGI::App::Directory root=.
CONSTRUCTOR ARGUMENTS
Arguments after the app specifier are parsed as key=value pairs and passed to the module constructor:
pagi-server PAGI::App::Directory root=/var/www show_hidden=1
Becomes:
PAGI::App::Directory->new(root => '/var/www', show_hidden => 1)->to_app
METHODS
new
my $runner = PAGI::Runner->new(%options);
Creates a new runner instance. Options:
- host => $host
-
Bind address. Default:
'127.0.0.1'(localhost only)The default is secure - it only accepts local connections. For headless servers or deployments requiring remote access, use
'0.0.0.0'to bind to all IPv4 interfaces. See PAGI::Server for detailed documentation - port => $port
-
Bind port. Default: 5000
- workers => $num
-
Number of worker processes. Default: 1
- listener_backlog => $num
-
Listener queue size. No default, if left blank then the server sets a default that is rational for itself.
- timeout => $num
-
Seconds before we timeout the request. If left blank will default to whatever is default for the server.
- quiet => $bool
-
Suppress startup messages. Default: 0
- loop => $loop_type
-
Event loop backend (EV, Epoll, UV, Poll). Default: auto-detect
- ssl_cert => $path
-
Path to SSL certificate file.
- ssl_key => $path
-
Path to SSL private key file.
- access_log => $path
-
Path to access log file. Default: STDERR
- no_access_log => $bool
-
Disable access logging entirely. Eliminates per-request I/O overhead, which can improve throughput by 5-15% depending on workload. Default: 0
- log_level => $level
-
Controls the verbosity of server log messages. Valid levels from least to most verbose: 'error', 'warn', 'info', 'debug'. Default: 'info'
- reuseport => $bool
-
Enable SO_REUSEPORT mode for multi-worker servers. Each worker creates its own listening socket, allowing the kernel to distribute connections. Reduces accept() contention and can improve p99 latency under high concurrency. Default: 0
- max_receive_queue => $count
-
Maximum WebSocket receive queue size (message count). When exceeded, connection is closed with code 1008. DoS protection for slow consumers. Default: 1000
- max_ws_frame_size => $bytes
-
Maximum WebSocket frame payload size in bytes. When a client sends a frame larger than this limit, the connection is closed. Default: 65536 (64KB)
- max_requests => $count
-
Maximum requests per worker before restart. Default: 0 (unlimited)
- max_connections => $count
-
Maximum concurrent connections per worker. Default: 0 (auto-detect). See "max_connections" in PAGI::Server for details.
- max_body_size => $bytes
-
Maximum request body size in bytes. Default: 10,000,000 (10MB). Set to 0 for unlimited. See "max_body_size" in PAGI::Server for details.
- libs => \@paths
-
Additional library paths to add to @INC before loading the app. Similar to
perl -I. Default: [] - daemonize => $bool
-
Fork to background and detach from terminal. Default: 0
- pid_file => $path
-
Write process ID to this file. Useful for init scripts and process managers.
- user => $username
-
Drop privileges to this user after binding to port. Requires starting as root.
- group => $groupname
-
Drop privileges to this group after binding to port. Requires starting as root.
parse_options
my @remaining = $runner->parse_options(@args);
Parses CLI options from the argument list. Known options are extracted and stored in the runner object. Returns remaining arguments (app specifier and constructor args).
Supported options:
-I, --lib Add path to @INC (repeatable, like perl -I)
-a, --app App file path (legacy, for backward compatibility)
-h, --host Bind address
-p, --port Bind port
-w, --workers Number of workers
-l, --loop Event loop backend
--ssl-cert SSL certificate path
--ssl-key SSL key path
--access-log Access log path
--no-access-log Disable access logging (for max performance)
--log-level Log verbosity: debug, info, warn, error (default: info)
--reuseport Enable SO_REUSEPORT for multi-worker scaling
--max-requests Requests per worker before restart (default: unlimited)
-q, --quiet Suppress output
--help Show help
load_app
my $app = $runner->load_app();
my $app = $runner->load_app($app_spec);
my $app = $runner->load_app($app_spec, %constructor_args);
Loads a PAGI application. If no app_spec is provided and one was set via parse_options, uses that. If still no app_spec, defaults to PAGI::App::Directory with root set to current directory.
Returns the loaded app coderef and stores it in the runner.
prepare_server
my $server = $runner->prepare_server;
Creates and configures a PAGI::Server instance based on the runner's settings. The app must be loaded first via load_app.
Returns the server instance (not yet started).
run
$runner->run(@args);
Convenience method that parses options, loads the app, creates the server, and runs the event loop. This is the main entry point for CLI usage.
SEE ALSO
AUTHOR
John Napiorkowski <jjnapiork@cpan.org>
LICENSE
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.