NAME

PAGI::Server::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::Server::Runner;

PAGI::Server::Runner->run(@ARGV);

DESCRIPTION

PAGI::Server::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::Server::Runner supports environment modes similar to Plack's -E flag:

development

Auto-enables PAGI::Middleware::Lint with strict mode to catch specification violations early (when PAGI-Tools is installed). 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 and new is called with the provided key=value arguments. The constructed value may be a native PAGI coderef or an instantiated application-provider object. A provider is normalized by calling to_app exactly once; to_app is never invoked as a class method.

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 either a native PAGI coderef or an instantiated application-provider object. A provider is normalized through to_app exactly once before the server is constructed.

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::Server::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::Server::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 are passed separately via the server_options hashref (see "load_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 => ".")'

Server-Specific Options

Server-specific options should be parsed by the server's CLI wrapper (e.g., bin/pagi-server) and passed to Runner via the server_options hashref parameter. This keeps Runner server-agnostic.

See PAGI::Server for available options when using pagi-server.

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. Every accepted loading form is normalized to and returns the native PAGI app coderef used by the server.

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 if available (requires PAGI-Tools).

load_server

my $server = $runner->load_server;

Constructs the configured server class (-s CLASS, default PAGI::Server) according to this runner's backend convention: $class->new(%options) followed by $server->run. This is a PAGI::Server::Runner plugin interface, not a construction API required by PAGI::Spec::Server.

Creates the server instance with the prepared app and configuration. Parses server-specific options and passes them to the server constructor.

run

PAGI::Server::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::Server::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 by load_server()

  • Development mode now auto-enables Lint middleware (when PAGI-Tools is installed)

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.