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
# With environment modes
pagi-server -E development app.pl # enable Lint middleware
pagi-server -E production app.pl # no auto-middleware
PAGI_ENV=production pagi-server app.pl
# Programmatic usage
use PAGI::Runner;
PAGI::Runner->run(@ARGV);
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), environment modes, and server orchestration.
The runner is designed to be server-agnostic. Common options like host, port, and daemonize are handled by the runner, while server-specific options are passed through to the server backend.
ENVIRONMENT MODES
PAGI::Runner supports environment modes similar to Plack's -E flag:
- development
-
Auto-enables PAGI::Middleware::Lint with strict mode to catch specification violations early. This is the default when running interactively (TTY detected).
- production
-
No middleware is auto-enabled. This is the default when running non-interactively (no TTY, e.g., systemd, docker, cron).
- none
-
Explicit opt-out of all auto-middleware, regardless of TTY detection.
Mode is determined by (in order of precedence):
1. -E / --env command line flag
2. PAGI_ENV environment variable
3. Auto-detection: TTY = development, no TTY = production
After determining the mode, the runner sets PAGI_ENV to the resolved value. This allows your application to check $ENV{PAGI_ENV} to know what mode it's running in, similar to Plack's PLACK_ENV.
Use --no-default-middleware to disable auto-middleware while keeping the mode for other purposes.
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.
For compatibility with Plack's plackup, the runner localizes $0 to the app file before loading it. This ensures FindBin::Bin resolves to the app file directory inside the app. If FindBin was already loaded, the runner also calls FindBin::again() to refresh its cached path.
Default
If no app is specified, defaults to serving the current directory:
pagi-server # same as: PAGI::App::Directory root=.
METHODS
run
PAGI::Runner->run(@ARGV);
Class method that creates a runner, parses options, loads the app, and runs the server. This is the main entry point for CLI usage.
new
my $runner = PAGI::Runner->new(%options);
Creates a new runner instance. Most users should use run() instead.
parse_options
$runner->parse_options(@args);
Parses CLI options from the argument list. Common options are stored in the runner object. Server-specific options (those not recognized) are collected for pass-through to the server.
Common Options (handled by Runner)
-a, --app FILE Load app from file (legacy option)
-e CODE Inline app code (like perl -e)
-M MODULE Load MODULE before -e (repeatable, like perl -M)
-o, --host HOST Bind address (default: 127.0.0.1)
-p, --port PORT Bind port (default: 5000)
-s, --server CLASS Server class (default: PAGI::Server)
-E, --env MODE Environment mode (development, production, none)
-I, --lib PATH Add PATH to @INC (repeatable)
-l, --loop BACKEND Event loop backend (EV, Epoll, UV, Poll)
-D, --daemonize Run as background daemon
--access-log FILE Access log file (default: STDERR)
--no-access-log Disable access logging
--pid FILE Write PID to file
--user USER Run as specified user (after binding)
--group GROUP Run as specified group (after binding)
-q, --quiet Suppress startup messages
--default-middleware Toggle mode middleware (default: on)
-v, --version Show version info
--help Show help
Example with -e and -M:
pagi-server -MPAGI::App::File -e 'PAGI::App::File->new(root => ".")->to_app'
Server-Specific Options (passed through)
All unrecognized options starting with - are passed to the server. For PAGI::Server, these include:
-w, --workers Number of worker processes
--reuseport Enable SO_REUSEPORT mode
--ssl-cert, --ssl-key TLS configuration
--max-requests, --max-connections, --max-body-size
--timeout, --log-level, etc.
See PAGI::Server for the full list of server-specific options.
mode
my $mode = $runner->mode;
Returns the current environment mode. Determines mode by checking (in order): explicit -E flag, PAGI_ENV environment variable, or auto-detection based on TTY.
load_app
my $app = $runner->load_app;
Loads the PAGI application based on the app specifier from command line arguments. Returns the app coderef.
prepare_app
my $app = $runner->prepare_app;
Loads the app and wraps it with mode-appropriate middleware. In development mode (with default_middleware enabled), wraps with PAGI::Middleware::Lint.
load_server
my $server = $runner->load_server;
Creates the server instance with the prepared app and configuration. Parses server-specific options and passes them to the server constructor.
run
PAGI::Runner->run(@ARGV);
$runner->run(@ARGV);
Main entry point. Parses options, loads the app, creates the server, and delegates to $server->run() which manages the event loop.
BREAKING CHANGES
As of version 1.0, PAGI::Runner has been refactored to be server-agnostic:
Server-specific options are now passed through to the server
The
prepare_server()method has been replaced byload_server()Development mode now auto-enables Lint middleware
The CLI interface is unchanged - existing command-line usage continues to work as before.
SEE ALSO
PAGI::Server, PAGI::Middleware::Lint, Plack::Runner
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.