NAME

PAGI::Endpoint::HTTP - Class-based HTTP endpoint handler

SYNOPSIS

package MyApp::UserAPI;
use parent 'PAGI::Endpoint::HTTP';
use Future::AsyncAwait;

async sub get {
    my ($self, $ctx) = @_;
    my $users = get_all_users();
    return $ctx->json($users);
}

async sub post {
    my ($self, $ctx) = @_;
    my $data = await $ctx->request->json;
    my $user = create_user($data);
    return $ctx->json($user, status => 201);
}

async sub delete {
    my ($self, $ctx) = @_;
    my $id = $ctx->request->path_param('id');
    delete_user($id);
    return $ctx->response->status(204)->empty;
}

# Use with PAGI server
my $app = MyApp::UserAPI->to_app;

DESCRIPTION

PAGI::Endpoint::HTTP provides a Starlette-inspired class-based approach to handling HTTP requests. Define methods named after HTTP verbs (get, post, put, patch, delete, head, options) and the endpoint automatically dispatches to them.

Features

  • Automatic method dispatch based on HTTP verb

  • 405 Method Not Allowed for undefined methods

  • OPTIONS handling with Allow header

  • HEAD falls back to GET if not defined

  • Customizable context class for framework integration

HTTP METHODS

Define any of these async methods to handle requests:

async sub get { my ($self, $ctx) = @_; ... }
async sub post { my ($self, $ctx) = @_; ... }
async sub put { my ($self, $ctx) = @_; ... }
async sub patch { my ($self, $ctx) = @_; ... }
async sub delete { my ($self, $ctx) = @_; ... }
async sub head { my ($self, $ctx) = @_; ... }
async sub options { my ($self, $ctx) = @_; ... }

Each receives:

$self - The endpoint instance
$ctx - A PAGI::Context::HTTP instance

Use $ctx->request for request data and $ctx->response for building responses.

Handler contract: Every HTTP handler MUST return a respond-able value (e.g. return $ctx->json(...)). Returning nothing (or an object without a respond method) causes dispatch to croak. The return value is what dispatch sends to the client via $ctx->respond($res).

Singleton: to_app creates a single endpoint instance that serves the entire application lifetime. State stored in $self persists across requests (within the same worker process).

Do not store per-request state on $self - one instance is shared by every request (and concurrent requests), so request-scoped data on $self will leak between them. Keep configuration and long-lived services on $self; put request-scoped data on $ctx (e.g. $ctx->stash).

CLASS METHODS

to_app

my $app = MyEndpoint->to_app;

Returns a PAGI-compatible async coderef that can be used directly with PAGI::Server or composed with middleware. Creates a single endpoint instance at construction time; that instance is reused for every request (singleton).

context_class

sub context_class { 'PAGI::Context' }

Override to use a custom context class.

INSTANCE METHODS

dispatch

await $endpoint->dispatch($ctx);

Dispatches the request to the appropriate HTTP method handler. Called automatically by to_app.

allowed_methods

my @methods = $endpoint->allowed_methods;

Returns list of HTTP methods this endpoint handles.

FRAMEWORK INTEGRATION

Framework designers can subclass and customize via context:

package MyFramework::Endpoint;
use parent 'PAGI::Endpoint::HTTP';

sub context_class { 'MyFramework::Context' }

SEE ALSO

PAGI::Context, PAGI::Endpoint::WebSocket, PAGI::Endpoint::SSE, PAGI::Request, PAGI::Response