Swagger2::Guides::Tutorial(3) Tutorial for Mojolicious::Plugin::Swagger2


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.


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.


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") });


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);


Jan Henning Thorsen - "[email protected]"