Mojolic...I::Cors(3)
π¦ Mojolicious::Plugin::OpenAPI::Cors(3) π¦
okay bestie, this page is from the User Contributed Perl Documentation section β yes, the header calls it Mojolic...I::Cors(3), and we're getting into it π
β¨
πΈ NAME πΈ
Mojolicious::Plugin::OpenAPI::Cors β an OpenAPI plugin for Cross-Origin Resource Sharing π«Ά
β¨ SYNOPSIS β¨
π Application π
Set add_preflighted_routes to 1, if you want Preflighted CORS requests to be sent to your already existing actions.
$app->plugin(OpenAPI => {add_preflighted_routes => 1, %openapi_parameters});
See register in Mojolicious::Plugin::OpenAPI for what %openapi_parameters might contain.
π Simple exchange π
The following example will automatically set default CORS response headers after validating the request against openapi_cors_allowed_origins:
package MyApp::Controller::User;
sub get_user {
my $c = shift->openapi->cors_exchange->openapi->valid_input or return;
# Will only run this part if both the cors_exchange and valid_input was successful.
$c->render(openapi => {user => {}});
}
π¦ Using the specification π¦
It's possible to enable preflight and simple CORS support directly in the specification. Here is one example:
"/user/{id}/posts": {
"parameters": [
{ "in": "header", "name": "Origin", "type": "string", "pattern": "https?://example.com" }
],
"options": {
"x-mojo-to": "#openapi_plugin_cors_exchange",
"responses": {
"200": { "description": "Cors exchange", "schema": { "type": "string" } }
}
},
"put": {
"x-mojo-to": "user#add_post",
"responses": {
"200": { "description": "Add a new post.", "schema": { "type": "object" } }
}
}
}
The special part can be found in the OPTIONS request. It has the x-mojo-to key set to #openapi_plugin_cors_exchange. This will enable Mojolicious::Plugin::OpenAPI::Cors to take over the route and add a custom callback to validate the input headers using regular OpenAPI rules and respond with a 200 OK and the default headers as listed under openapi.cors_exchange if the input is valid. The only extra part that needs to be done in the add_post() action is this:
sub add_post {
my $c = shift->openapi->valid_input or return;
# Need to respond with a "Access-Control-Allow-Origin" header if
# the input "Origin" header was validated
$c->res->headers->access_control_allow_origin($c->req->headers->origin)
if $c->req->headers->origin;
# Do the rest of your custom logic
$c->respond(openapi => {});
}
π Custom exchange π
If you need full control, you must pass a callback to openapi.cors_exchange:
package MyApp::Controller::User;
sub get_user {
# Validate incoming CORS request with _validate_cors()
my $c = shift->openapi->cors_exchange("_validate_cors")->openapi->valid_input or return;
# Will only run this part if both the cors_exchange and valid_input was
# successful.
$c->render(openapi => {user => {}});
}
# This method must return undef on success. Any true value will be used as an error.
sub _validate_cors {
my $c = shift;
my $req_h = $c->req->headers;
my $res_h = $c->res->headers;
# The following "Origin" header check is the same for both simple and
# preflighted.
return "/Origin" unless $req_h->origin =~ m!^https?://whatever.example.com!;
# The following checks are only valid if preflighted...
# Check the Access-Control-Request-Headers header
my $headers = $req_h->header('Access-Control-Request-Headers');
return "Bad stuff." if $headers and $headers =~ /X-No-Can-Do/;
# Check the Access-Control-Request-Method header
my $method = $req_h->header('Access-Control-Request-Methods');
return "Not cool." if $method and $method eq "DELETE";
# Set the following header for both simple and preflighted on success
# or just let the auto-renderer handle it.
$c->res->headers->access_control_allow_origin($req_h->origin);
# Set Preflighted response headers, instead of using the default
if ($c->stash("openapi_cors_type") eq "preflighted") {
$c->res->headers->header("Access-Control-Allow-Headers" => "X-Whatever, X-Something");
$c->res->headers->header("Access-Control-Allow-Methods" => "POST, GET, OPTIONS");
$c->res->headers->header("Access-Control-Max-Age" => 86400);
}
# Return undef on success.
return undef;
}
π DESCRIPTION π
Mojolicious::Plugin::OpenAPI::Cors is a plugin for accepting Preflighted or Simple Cross-Origin Resource Sharing requests. See https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS for more details.
This plugin is loaded by default by Mojolicious::Plugin::OpenAPI.
Note that this plugin currently EXPERIMENTAL! Please comment on https://github.com/jhthorsen/mojolicious-plugin-openapi/pull/102 if you have any feedback or create a new issue. π
π§ STASH VARIABLES π§
The following stash variables can be set in defaults in Mojolicious, to in Mojolicious::Routes::Route or stash in Mojolicious::Controller.
πΈ openapi_cors_allowed_origins πΈ
This variable should hold an array-ref of regexes that will be matched against the Origin header in case the default openapi_cors_default_exchange_callback is used. Examples:
$app->defaults(openapi_cors_allowed_origins => [qr{^https?://whatever.example.com}]);
$c->stash(openapi_cors_allowed_origins => [qr{^https?://whatever.example.com}]);
π openapi_cors_default_exchange_callback π
This value holds a default callback that will be used by openapi.cors_exchange, unless you pass on a $callback. The default provided by this plugin will simply validate the Origin header against openapi_cors_allowed_origins.
Here is an example to allow every Origin
$app->defaults(openapi_cors_default_exchange_callback => sub {
my $c = shift;
$c->res->headers->header("Access-Control-Allow-Origin" => "*");
return undef;
});
π¦ openapi_cors_default_max_age π¦
Holds the default value for the Access-Control-Max-Age response header set by openapi.cors_preflighted. Examples:
$app->defaults(openapi_cors_default_max_age => 86400);
$c->stash(openapi_cors_default_max_age => 86400);
Default value is 1800.
π« openapi_cors_type π«
This stash variable is available inside the callback passed on to openapi.cors_exchange. It will be either preflighted, real or simple. real is the type that comes after preflighted when the actual request is sent to the server, but with Origin header set.
π HELPERS π
π openapi.cors_exchange π
$c = $c->openapi->cors_exchange($callback);
$c = $c->openapi->cors_exchange("MyApp::cors_validator");
$c = $c->openapi->cors_exchange("_some_controller_method");
$c = $c->openapi->cors_exchange(sub { ... });
$c = $c->openapi->cors_exchange;
Used to validate either a simple CORS request, preflighted CORS request or a real request. It will be called as soon as the Origin request header is seen.
The $callback will be called with the current Mojolicious::Controller object and must return an error or undef() on success:
my $error = $callback->($c);
The $error must be in one of the following formats:
undef()β Returningundef()means that the CORS request is valid.- A string starting with
/β Shortcut for generating a400 Bad Requestresponse with a header name. Example:
return "/Access-Control-Request-Headers";
- Any other string β Used to generate a
400 Bad Requestresponse with a completely custom message. - An array-ref β Used to generate a completely custom
400 Bad Requestresponse. Example:
return [{message => "Some error!", path => "/Whatever"}];
return [{message => "Some error!"}];
return [JSON::Validator::Error->new];
On success, the following headers will be set, unless already set by $callback:
Access-Control-Allow-Headersβ Set to the header of the incomingAccess-Control-Request-Headersheader.Access-Control-Allow-Methodsβ Set to the list of HTTP methods defined in the OpenAPI spec for this path.Access-Control-Allow-Originβ Set to theOriginheader in the request.Access-Control-Max-Ageβ Set toopenapi_cors_default_max_age.
π METHODS π
π register π
Called by Mojolicious::Plugin::OpenAPI.
π¦ SEE ALSO π¦
Mojolicious::Plugin::OpenAPI.
okay that's the whole page, bestie π β it's serving perl v5.42.0 energy, dated 2025-08-03, and the footer manual name is Mojolic...I::Cors(3). slay β¨
π¦ where this page comes from
- opensuse-leap 16.0: perl-Mojolicious-Plugin-OpenAPI 5.110.0-bp160.1.1 Β· Artistic-2.0
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms