NAME
Mojolicious::Plugin::Swagger2 - Mojolicious plugin for Swagger2
DESCRIPTION
Mojolicious::Plugin::Swagger2 is Mojolicious::Plugin that add routes and input/output validation to your Mojolicious application.
Have a look at this example blog app too see a complete working example, with a database backend. Questions and comments on how to improve the example are very much welcome.
SYNOPSIS
Swagger specification
The input "url" to given as argument to the plugin need to point to a valid swagger document.
Every operation must have a "x-mojo-controller" specified, so this plugin knows where to look for the decamelized "operationId", which is used as method name.
---
swagger: 2.0
basePath: /api
paths:
/foo:
get:
x-mojo-controller: MyApp::Controller::Api
x-mojo-around-action: MyApp::authenticate_api_request
operationId: listPets
parameters: [ ... ]
responses:
200: { ... }
Application
The application need to load the Mojolicious::Plugin::Swagger2 plugin, with a URL to the API specification. The plugin will then add all the routes defined in the "Swagger specification".
use Mojolicious::Lite;
plugin Swagger2 => { url => app->home->rel_file("api.yaml") };
app->start;
Controller
The method names defined in the controller will be a decamelized version of operationId
.
The example "Swagger specification" above, will result in list_pets()
in the controller below to be called. This method will receive the current Mojolicious::Controller object, input arguments and a callback. The callback should be called with a HTTP status code, and a data structure which will be validated and serialized back to the user agent.
package MyApp::Controller::Api;
sub list_pets {
my ($c, $input, $cb) = @_;
$c->$cb({foo => 123}, 200);
}
Protected API
It is possible to protect your API, using a custom route:
use Mojolicious::Lite;
my $route = app->routes->under->to(
cb => sub {
my $c = shift;
return 1 if $c->param('secret');
return $c->render(json => {error => "Not authenticated"}, status => 401);
}
);
plugin Swagger2 => {
route => $route,
url => app->home->rel_file("api.yaml")
};
Custom placeholders
The default placeholder type is the generic placeholder, meaning ":". This can be customized using x-mojo-placeholder
in the API specification. The example below will enforce a relaxed placeholder:
---
swagger: 2.0
basePath: /api
paths:
/foo:
get:
x-mojo-controller: MyApp::Controller::Api
operationId: listPets
parameters:
- name: ip
in: path
type: string
x-mojo-placeholder: "#"
responses:
200: { ... }
Around action hook
The x-mojo-around-action
value is optional, but can hold the name of a method to call, which wraps around the autogenerated action which does input and output validation. This means that any data sent to the server is not yet converted into $input
to your action.
Here is an example method which match the x-mojo-around-action
from "Swagger specification", MyApp::authenticate_api_request
:
package MyApp;
sub authenticate_api_request {
my ($next, $c, $action_spec) = @_;
# Go to the action if the Authorization header is valid
return $next->($c) if $c->req->headers->authorization eq "s3cret!";
# ...or render an error if not
return $c->render_swagger(
{errors => [{message => "Invalid authorization key", path => "/"}]},
{},
401
);
}
This feature is EXPERIMENTAL and can change without notice.
ATTRIBUTES
url
Holds the URL to the swagger specification file.
HELPERS
render_swagger
$c->render_swagger(\%err, \%data, $status);
This method is used to render %data
from the controller method. The %err
hash will be empty on success, but can contain input/output validation errors. $status
is the HTTP status code to use:
200
The default
$status
is 200, unless the method handling the request sent back another value.%err
will be empty in this case.400
This module will set
$status
to 400 on invalid input.%err
then contains a data structure describing the errors. The default is to render a JSON document, like this:{ "valid": false, "errors": [ { "message": "string value found, but a integer is required", "path": "/limit" }, ... ] }
500
This module will set
$status
to 500 on invalid response from the handler.%err
then contains a data structure describing the errors. The default is to render a JSON document, like this:{ "valid": false, "errors": [ { "message": "is missing and it is required", "path": "/foo" }, ... ] }
501
This module will set
$status
to 501 if the given controller has not implemented the required method.%err
then contains a data structure describing the errors. The default is to render a JSON document, like this:{ "valid": false, "errors": [ { "message": "No handler defined.", "path": "/" } ] }
METHODS
register
$self->register($app, \%config);
This method is called when this plugin is registered in the Mojolicious application.
%config
can contain these parameters:
route
Need to hold a Mojolicious route object. See "Protected API" for an example.
This parameter is optional.
swagger
A
Swagger2
object. This can be useful if you want to keep use the specification to other things in your application. Example:use Swagger2; my $swagger = Swagger2->new->load($url); plugin Swagger2 => {swagger => $swagger2}; app->defaults(swagger_spec => $swagger->tree);
Either this parameter or
url
need to be present.url
This will be used to construct a new Swagger2 object. The
url
can be anything that "load" in Swagger2 can handle.Either this parameter or
swagger
need to be present.
COPYRIGHT AND LICENSE
Copyright (C) 2014, Jan Henning Thorsen
This program is free software, you can redistribute it and/or modify it under the terms of the Artistic License version 2.0.
AUTHOR
Jan Henning Thorsen - jhthorsen@cpan.org