NAME
    Mojolicious::Plugin::OpenAPI - OpenAPI / Swagger plugin for Mojolicious

SYNOPSIS
  Specification
    This plugin reads an OpenAPI specification
    <https://openapis.org/specification> and generate routes and
    input/output rules from it. See JSON::Validator for supported schema
    formats.

      {
        "basePath": "/api",
        "paths": {
          "/pets": {
            "get": {
              "x-mojo-to": "pet#list",
              "summary": "Finds pets in the system",
              "parameters": [],
              "responses": {
                "200": {
                  "description": "Pet response",
                  "schema": { "type": "array", "items": { "type": "object" } }
                },
                "default": {
                  "description": "Unexpected error",
                  "schema": { "$ref": "http://git.io/vcKD4#" }
                }
              }
            }
          }
        }
      }

    The non-standard part in the spec above is "x-mojo-to". The "x-mojo-to"
    key can either a plain string, object (hash) or an array. The string and
    hash will be passed directly to "to" in Mojolicious::Routes::Route,
    while the array ref, will be flattened first. Examples:

      "x-mojo-to": "pet#list"
      $route->to("pet#list");

      "x-mojo-to": {"controller": "pet", "action": "list", "foo": 123}
      $route->to({controller => "pet", action => "list", foo => 123);

      "x-mojo-to": ["pet#list", {"foo": 123}]
      $route->to("pet#list", {foo => 123});

    The complete HTTP request for getting the "pet list" will be "GET
    /api/pets" The first part of the path ("/api") comes from "basePath",
    the second part comes from the key under "paths", and the HTTP method
    comes from the key under "/pets".

    "parameters" and "responses" will be used to define rules for input and
    output.

  Application
      package Myapp;
      use Mojolicious;

      sub startup {
        my $app = shift;
        $app->plugin("OpenAPI" => {url => $app->home->rel_file("myapi.json")});
      }

    The first thing in your code that you need to do is to load this plugin
    and the "Specification". See "register" for information about what the
    plugin config can be, in addition to "url".

  Controller
      package Myapp::Controller::Pet;

      sub list {
        my $c = shift;

        # You might want to introspect the specification for the current route
        my $spec = $c->openapi->spec;
        unless ($spec->{'x-opening-hour'} == (localtime)[2]) {
          return $c->reply->openapi([], 498);
        }

        # $input will be a hash ref if validated and undef on invalid input
        my $input = $c->openapi->input or return;

        # $output will be validated by the OpenAPI spec before rendered
        my $output = {pets => [{name => "kit-e-cat"}]};
        $c->reply->openapi($output, 200);
      }

    The input and output to the action will only be validated if the
    "openapi.input" and "reply.openapi" methods are used.

    All OpenAPI powered actions will have auto-rendering enabled, which
    means that the "return;" above will render an error document.

DESCRIPTION
    Mojolicious::Plugin::OpenAPI will replace Mojolicious::Plugin::Swagger2.

    This plugin is currently EXPERIMENTAL.

HELPERS
  openapi.input
      $hash = $c->openapi->input;

    Returns the request parameters if they are valid, and "undef" on invalid
    input.

  openapi.spec
      $hash = $c->openapi->spec;

    Returns the OpenAPI specification for the current route. Example:

      {
        "paths": {
          "/pets": {
            "get": {
              // This datastructure is returned
            }
          }
        }
      }

  openapi.validate
      # validate request
      @errors = $c->openapi->validate;

      # validate response
      @errors = $c->openapi->validate($output, $http_status);

    Used to validate input or output data. Request validation is always done
    by "openapi.input".

  reply.openapi
      $c->reply->openapi(\%output, $http_status);

    Will validate %output before passing it on to "render" in
    Mojolicious::Controller. Note that %output will be passed on using the
    format key in stash, which defaults to "json". This also goes for
    auto-rendering. Example:

      my $format = $c->stash("format") || "json";
      $c->render($format => \%output);

METHODS
  register
      $self->register($app, \%config);

    Loads the OpenAPI specification, validates it and add routes to $app. It
    will also set up "HELPERS" and adds a before_render hook for
    auto-rendering of error documents.

    %config can have:

    * coerce

      See "coerce" in JSON::Validator for possible values that "coerce" can
      take.

      Default: 1

    * log_level

      "log_level" is used when logging invalid request/response error
      messages.

      Default: "warn".

    * route

      "route" can be specified in case you want to have a protected API.
      Example:

        $app->plugin(OpenAPI => {
          route => $app->routes->under("/api")->to("user#auth"),
          url   => $app->home->rel_file("cool.api"),
        });

    * url

      See "schema" in JSON::Validator for the different "url" formats that
      is accepted.

TODO
    This plugin is still a big rough on the edges, but I decided to release
    it on CPAN so people can start playing around with it.

    * Add WebSockets support
      <https://github.com/jhthorsen/mojolicious-plugin-openapi/compare/webso
      cket>.

    * Add support for /api.html (human readable documentation)

    * Never add support for "x-mojo-around-action", but possibly "before
      action".

AUTHOR
    Jan Henning Thorsen

COPYRIGHT AND LICENSE
    Copyright (C) 2016, 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.

SEE ALSO
    Mojolicious::Plugin::Swagger2.

