PAGI is a specification for asynchronous Perl web applications, designed as a spiritual successor to PSGI. It defines a standard interface between async-capable Perl web servers, frameworks, and applications, supporting HTTP/1.1, WebSocket, and Server-Sent Events (SSE).
- docs/ - PAGI specification documents
- examples/ - Reference PAGI applications (raw PAGI and PAGI::Simple)
- lib/ - Reference server implementation (PAGI::Server) and micro-framework (PAGI::Simple)
- bin/ - CLI launcher (pagi-server)
- t/ - Test suite
- Perl 5.32+ (required for native subroutine signatures)
- cpanminus (for dependency installation)
# Set up environment (installs dependencies)
cpanm --installdeps .
# Run tests
prove -l t/
# Start the server with a raw PAGI app
pagi-server --app examples/01-hello-http/app.pl --port 5000
# Or with a PAGI::Simple app
pagi-server --app examples/simple-01-hello/app.pl --port 5000
# Test it
curl http://localhost:5000/PAGI applications are async coderefs with this signature:
use Future::AsyncAwait;
use experimental 'signatures';
async sub app ($scope, $receive, $send) {
die "Unsupported: $scope->{type}" if $scope->{type} ne 'http';
await $send->({
type => 'http.response.start',
status => 200,
headers => [ ['content-type', 'text/plain'] ],
});
await $send->({
type => 'http.response.body',
body => "Hello from PAGI!",
more => 0,
});
}- $scope - Hashref containing connection metadata (type, headers, path, etc.)
- $receive - Async coderef returning a Future that resolves to the next event
- $send - Async coderef taking an event hashref, returning a Future
http- HTTP request/response (one scope per request)websocket- Persistent WebSocket connectionsse- Server-Sent Events streamlifespan- Process startup/shutdown lifecycle
For simpler applications, use the PAGI::Simple micro-framework:
use PAGI::Simple;
my $app = PAGI::Simple->new(name => 'My App');
$app->get('/' => sub ($c) {
$c->text("Hello, World!");
});
$app->get('/greet/:name' => sub ($c) {
my $name = $c->path_params->{name};
$c->json({ greeting => "Hello, $name!" });
});
$app->websocket('/ws' => sub ($ws) {
$ws->on(message => sub ($data) {
$ws->send("Echo: $data");
});
});
$app->to_app;These examples demonstrate the low-level PAGI protocol directly:
| Example | Description |
|---|---|
| 01-hello-http | Basic HTTP response |
| 02-streaming-response | Chunked streaming with trailers |
| 03-request-body | POST body handling |
| 04-websocket-echo | WebSocket echo server |
| 05-sse-broadcaster | Server-Sent Events |
| 06-lifespan-state | Shared state via lifespan |
| 07-extension-fullflush | TCP flush extension |
| 08-tls-introspection | TLS connection info |
| 09-psgi-bridge | PSGI compatibility |
These examples use the PAGI::Simple micro-framework for easier development:
| Example | Description |
|---|---|
| simple-01-hello | Basic routing, path params, JSON/HTML responses |
| simple-02-forms | Form processing, REST API, CRUD operations |
| simple-03-websocket | WebSocket chat with rooms and broadcasting |
| simple-04-sse | Server-Sent Events with channels |
# Install development dependencies
cpanm --installdeps . --with-develop
# Build distribution
dzil build
# Run distribution tests
dzil testSee docs/specs/main.mkdn for the complete PAGI specification.
This software is licensed under the same terms as Perl itself.
John Napiorkowski jjnapiork@cpan.org