NAME

Punk::Mount::OpenAPI - the api mount: spec-first operations

SYNOPSIS

my $v1  = under '/v1' => 'API::Auth#bearer';
my $api = $v1->api('openapi.json' => {
    controller_ns => 'MyApp::Controller::API',   # the default
    under         => { '/books/manage' => 'API::Auth#admin' },
    security      => { session => 'API::Auth#session' },
});

DESCRIPTION

An api mount compiles an OpenAPI 3.1 document through Open::API and dispatches each operation to the controller method named after its operationId. Everything resolves at to_app:

  • every class under controller_ns (default MyApp::Controller::API) is loaded and operationIds mapped to the one class implementing each - two implementers croak, none croaks (unless stub => 1, which answers 501 per request instead); the handlers option overrides per operationId with a coderef or target string;

  • the spec's security requirements compile to a generated guard per operation from the security => { scheme => checker } map - alternatives are OR, schemes within one are AND, results land in $c->stash->{auth}, failure answers 401 before any validation. A required scheme with no checker croaks at boot;

  • the under option assigns extra guards by spec-path prefix (longest prefix wins), appended after the mount scope's own guards.

Per request the pipeline is: route ($api->match, one C call), guard chain (a 401/redirect costs no body read), max_body_size check (413), $api->validate_request (one C call; failures answer 400 with the same {errors=>[...]} shape as Open::API::Plack), then the controller with $c->openapi holding the typed parameters and $c->param reading them first.

METHODS

The mount is an internal object: the api keyword returns it and the framework drives it.

new(spec => $spec, opts => \%opts, prefix => $prefix, guards => \@guards)

Records a mount; nothing is resolved until "compile".

compile($app, $resolve)

Run at to_app: resolves every operationId to its controller method and freezes each operation's guard chain (the scope's guards, then the spec's security requirement, then the under guards). Croaks on anything unresolved. Returns the mount.

dispatch($c, $before, $op_id, \%captures)

Runs one matched operation for a request: the before_dispatch hooks, the guards, the body-size check, validation and the controller. Returns ($ret, $err) for the application's response path.

prefix

The path the mount is under.

api

The compiled Open::API.

ops

The compiled operations, a hashref keyed by operationId.

max_body_size

The body ceiling in bytes; see "OPTIONS".

on_error

The mount's own error handler, or undef.

OPTIONS

controller_ns, handlers, under, security, max_body_size (default 1048576), on_error (mount-level override), stub.

SEE ALSO

Punk, Open::API, Open::API::Plack.

AUTHOR

LNATION <email@lnation.org>

LICENSE AND COPYRIGHT

This software is Copyright (c) 2026 by LNATION <email@lnation.org>.

This is free software, licensed under:

The Artistic License 2.0 (GPL Compatible)