REST endpoint declaration domain language

Note

This topic describes how to use REST API docstring documentation domain language when developing REST APIs with Micro.Rest

Rationale

Our approach to creating self-documented REST APIs is to have a list of REST API endpoints verbatim with documentation and validation schema defined in each endpoint method docstring. The list of REST API endpoints is served with any API server instance at pre-defined /swagger.json endpoint (see Pre-created system routes).

Docstrings domain language

The domain language we use for documenting REST endpoints is basically Javadoc subset with some ‘magic’ javadoc block tags which are translated into validation schemas or Swagger entities. Every REST API endpoint is mapped into Swagger operation object, the most of domain language functionality is assigned for translating various magic javadoc tags into Swagger operation object fields. The functions which are treated as rest endpoints should be decorated with both micro.web.Micro.route() and Micro.Rest decorators decorators strictly in that order. The most simple endpoint declaration with use of docstrings domain language is:

from micro.web import Micro
from micro.rest import rest

app = Micro()

@rest()
@app.route("/")
def main():
    """
    I am a simple method which accepts any input
        and returns 204 No Content
    @output 204 `No Content`
    """
    return ""

Method description

The docstring part which starts from the actual start of docsting serves as description field of Swagger operation object. Description is required for every API method, the absense of decsription will make an application with such endpoint fail on start. Moreover, the most failures in docstrings are detected and validated on the application start too.

Docstring magic tags

The following is the list of Javadoc tags which are translated into Swagger endpoints. The only required tag which should be explicitly present in every docstring is @output. Any other tags are mandatory.

@output

This defines the successful output schema for REST API endpoint. The first argument of the tag MUST be a HTTP status code which should be returned if the method performs without any exceptions and output passes (mandatory) validation. The second argument is mandatory and defines the schema of JSON object which method returns (see Schema definition language). A single REST endpoint docstring MUST have only one @output tag

Examples:

@output 200 {}; `Empty object`

@output 204 {} -> EmptyObject; `Empty object`

@output_desc

This defines the description of the successful output and mapped into Swagger response object description field.

Example:

@output_desc I am the description of successful response!

@raises

This defines the error cases for response. The first argument of the tag MUST be a full path to a exception class that inherits aiohttp.web_exceptions.HTTPError. The second argument of the tag is mandatory description of the error response. A single REST endpoint may have multiple @raises tags. This mapped into Swagger response object , the status_code property of the exception class represented as response status.

Example:

@raises aiohttp.web_exceptions.HTTPNotFound
    When the enitity is not found

@input

This defines an input body JSON schema for validation (see Schema definition language). A single REST endpoint MAY have no more than one @input tag. This tag mapped into Swagger parameter object which should appear in ‘body’ section.

Examples:

@input object {};

@input object {
    string world
    `The world as a string`;
} -> World;

@input_uri

This defines an URI input parameter. This tag does not affect the validation behavior; however, there should be as many input_uri parameters as aiohttp`s variable routes in micro.web.app.Micro.route() first (URI) argument, and their names should be equal between REST method docstring and route argument. See Aiohttp docs on handlers for more on aiohttp variable routes. This tag mapped into Swagger parameter object which should appear in ‘Path’ section.

Example:

@input_uri arg `hello`

@input_query

This defines a query input parameter. This tag does not affect the validation behavior. The tag is mapped into Swagger parameter object which should appear in ‘Query’ section.

Example:

@input_query input_uri arg `hello`

@summary

This defines a Swagger summary for REST API endpoint, and is mapped into Swagger operation object summary field. If this tag is not present in the docstring, the Method description , shortened for 120 chars only (as Swagger operation object documentation for summary field states) will be used as summary. Summary length is limited to 120 characters

Example:

@summary I am the summary of the method.

@operation_id

This defines a Swagger operation ID for REST API endpoint and is mappend into Swagger operation object operation ID field. If this tag is not present in the docstring, the Hipchat.Micro.Core`s micro.web.Micro.route() endpoint name will be used as operation ID. Operation ID will not contain whitespace or line breaks.

Example:

@operation_id I_am_Operation_ID_of_the_method

Schema definition language

Micro.Rest uses the regular Orderly JSON as schema definition language with one addition to the standard. It is possible to define Swagger definition objects with -> operator, see example:

object {
    string {1,1000} message
        `The message`;
    string parentMessageId
     `The id of the message you are replying to`;
    } `Message object` -> Message;

That OrderlyJSON object, translated into jsonschema, should appear in the Swagger definition objects list with Message name. You can map nested schemas into objects too, see example:

object {
  object {
     string user_name;
     string user_id;
  } user_record `The record for a user` -> UserRecord;
  string name;
};

The OrderlyJSON object user_record, translated into jsonschema, should appear in the Swagger definition objects list with name UserRecord. The whole object should have a Swagger reference to the inner user_record object.