PAGI
view release on metacpan or search on metacpan
docs/introduction.mkdn view on Meta::CPAN
# Introduction
**PAGI** is a spiritual successor to
[PSGI](https://metacpan.org/dist/PSGI/view/PSGI.pod), the long-standing Perl
standard for compatibility between web servers, frameworks, and applications.
PSGI succeeded in allowing much more freedom and innovation in the Perl
web space, and PAGI's goal is to continue this onward into the land of
asynchronous Perl.
PAGI is a Perlish port of the original Python specification ASGI, updated with Perl-first terminology and tooling.
## What's wrong with PSGI?
PSGI applications are a single, synchronous coderef that takes a request and
returns a response; this doesn't allow for long-lived connections, like you
get with long-poll HTTP or WebSocket connections.
Even if we made this coderef asynchronous, it still only has a single path
to provide a request, so protocols that have multiple incoming events (like
receiving WebSocket frames) can't trigger this.
## How does PAGI work?
PAGI is structured as a single, asynchronous coderef. It takes a `scope`,
which is a hashref containing details about the specific connection,
`send`, an asynchronous coderef that lets the application send event messages
to the client, and `receive`, an asynchronous coderef which lets the application
receive event messages from the client. Both coderefs return `Future` objects to
make back-pressure explicit.
This not only allows multiple incoming events and outgoing events for each
application, but also allows for a background process or coroutine so the application
can do other things (such as listening for events on an external trigger, like a
Redis queue).
In its simplest form, an application can be written as an **asynchronous
function in modern Perl**, like this:
```perl
use Future::AsyncAwait;
async sub application ($scope, $receive, $send) {
# For example, if you're handling a WebSocket or HTTP scope:
my $event = await $receive->();
# ... do something with $event ...
await $send->({
type => 'websocket.send',
text => 'Hello from PAGI!',
});
}
```
Every *event* that you send or receive is a hashref,
with a predefined structure. It's these event formats that form the basis of the
standard, and allow applications to be swappable between servers.
These *events* each have a defined `type` key, which can be used to infer
the event's structure. Here's an example event that you might receive from
`$receive->()` with the body from an HTTP request:
```perl
{
type => "http.request",
body => "Hello World",
more => 0
}
```
And here's an example of an event you might pass to `$send->()` to send an
outgoing WebSocket message:
```perl
{
type => "websocket.send",
text => "Hello world!"
}
```
## PSGI compatibility
PAGI is also designed to be a superset of PSGI, and there's a defined way
of translating between the two, allowing PSGI applications to be run inside
PAGI servers through a translation wrapper (provided in libraries adapted from
`PAGI::Ref` for PAGI). A thread pool can be used to run the synchronous PSGI
applications away from the async event loop.
( run in 1.083 second using v1.01-cache-2.11-cpan-2398b32b56e )