OVERVIEW
This tutorial will give you an introduction to how to use Mojolicious::Plugin::Swagger2.You can also check out <https://github.com/jhthorsen/swagger2/tree/master/t/blog> if you want to look at a complete example application.
Another resources is the blog post <http://thorsen.pm/perl/programming/2015/07/05/mojolicious-swagger2.html>, which includes reasons for why you want to use Swagger2.
TUTORIAL
Swagger specification
The input ``url'' to given as argument to the plugin need to point to a valid swagger <https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md> document.Every operation must have ``operationId'' specified, so this plugin knows where to look for the controller and method. The naming convention is:
"operationId": "methodControllerOptions"
Example specification:
{
"swagger": "2.0",
"basePath": "/api",
"paths": {
"/pets/{petId}": {
"get": {
"operationId": "showPetById",
"parameters": [ ... ],
"responses": {
"200": { ... }
}
}
}
}
}
Here the ``operationId'' contains the method ``show'' and the controller ``Pet''. The ``Pet'' controller will again expand to "MyApp::Controller::Pet" or "MyApp::Pet" or whatever ``namespaces'' in Mojolicious::Routes is set to. The ``options'' part (ById) is simply ignored.
Note that ``showPetById'' and ``listPets'' will both result in looking for the ``Pet'' controller, since the plural ending (``s'') is removed.
The table below try to illustrate how the controller/method is resolved:
.---------------------------------------------------------------.
| operationId | Controller | Method | Ignored |
|------------------------|--------------|-------------|---------|
| childrenOfPerson | Person | children | Of |
| designByUser | User | design | By |
| fooWithBar | Bar | foo | With |
| getPetById | Pet | get | ById |
| listUsers | User | list | s |
| peopleInConversation | Conversation | people | In |
| searchForPets | Pet | search | For, s |
| sendToConversation | Conversation | send | To |
| createFileInFileSystem | FileSystem | create_file | In |
| removeFromFileSystem | FileSystem | remove | From |
'---------------------------------------------------------------'
The operationId rules will be updated if bugs or incompatibility is discovered.
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''.
package MyApp;
use Mojo::Base "Mojolicious";
sub startup {
my $app = shift;
$app->plugin(Swagger2 => { url => app->home->rel_file("api.json") });
}
Controller
The method names defined in the controller will be a decamelized version of "operationId".The example ``Swagger specification'' above, will result in "show()" 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.
$args (input arguments) will be a hash, where the keys match ``name'' in the ``parameters'' defined in the Swagger spec, and the values are whatever input came from the client. This also goes for the ``body'' parameter: This means that the input JSON from HTTP body will not be flattened, but stored under the body parameter name in $args.
package MyApp::Controller::Pet;
sub show {
my ($c, $args, $cb) = @_;
# Example $args:
# $args->{body_param_name} == $c->req->json
# $args->{query_param_name} == $c->req->url->query->param("query_param_name")
# $args->{"X-Header-Name"} == $c->req->headers->header("X-Header-Name")
$c->$cb({limit => 123}, 200);
}
AUTHOR
Jan Henning Thorsen - "jhthorsen@cpan.org"