PAGI-Server
view release on metacpan or search on metacpan
lib/PAGI/Server/Runner.pm view on Meta::CPAN
# won't have Future::IO integration. Apps that need it will get a
# helpful error message from PAGI::SSE->every() or similar.
}
sub _is_module_name {
my ($self, $spec) = @_;
return $spec =~ /::/;
}
sub _is_file_path {
my ($self, $spec) = @_;
return $spec =~ m{/} || $spec =~ /\.(?:pl|psgi)$/i;
}
sub _load_module {
my ($self, $module, %args) = @_;
# Validate module name (basic security check)
die "Invalid module name: $module\n"
unless $module =~ /^[A-Za-z_][A-Za-z0-9_]*(?:::[A-Za-z_][A-Za-z0-9_]*)*$/;
# Try to load the module
my $file = $module;
$file =~ s{::}{/}g;
$file .= '.pm';
eval { require $file };
if ($@) {
die "Cannot find module '$module': $@\n";
}
# Check for to_app method
unless ($module->can('new') && $module->can('to_app')) {
die "Module '$module' does not have new() and to_app() methods\n";
}
# Get the module's actual file path for correct home directory detection
my $module_file = $INC{$file};
# Instantiate and get app (pass _caller_file for correct home dir)
my $instance = $module->new(%args, _caller_file => $module_file);
my $app = $instance->to_app;
unless (ref $app eq 'CODE') {
die "Module '$module' to_app() did not return a coderef\n";
}
return $app;
}
sub _load_file {
my ($self, $file) = @_;
# Convert to absolute path
$file = File::Spec->rel2abs($file);
die "App file not found: $file\n" unless -f $file;
# Match plackup behavior so FindBin::Bin resolves to the app file directory
local $0 = $file;
local @ARGV = ($file);
if (exists $INC{'FindBin.pm'}) {
FindBin::again();
}
my $app = do $file;
if ($@) {
die "Error loading $file: $@\n";
}
if (!defined $app && $!) {
die "Error reading $file: $!\n";
}
unless (ref $app eq 'CODE') {
my $type = ref($app) || 'non-reference';
die "App file must return a coderef, got: $type\n";
}
return $app;
}
sub _parse_app_args {
my ($self, @args) = @_;
my %result;
for my $arg (@args) {
if ($arg =~ /^([^=]+)=(.*)$/) {
$result{$1} = $2;
}
else {
warn "Ignoring argument without '=': $arg\n";
}
}
return %result;
}
sub _show_help {
my ($self) = @_;
print <<'HELP';
Usage: pagi-server [options] [app] [key=value ...]
Common Options (handled by Runner):
-I, --lib PATH Add PATH to @INC (repeatable, like perl -I)
-a, --app FILE Load app from file (legacy option)
-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)
-l, --loop BACKEND Event loop backend (EV, Epoll, UV, Poll)
--access-log FILE Access log file (default: STDERR)
--no-access-log Disable access logging
-D, --daemonize Run as background daemon
--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
--no-default-middleware Disable mode-based middleware
-v, --version Show version info
--help Show this help
( run in 2.921 seconds using v1.01-cache-2.11-cpan-7e94247ccb0 )