swaggerize-express

Design-first REST services with Swagger and Express.

swaggerize-express

Lead Maintainer: Trevor Livingston


WARNING: This module now uses Swagger 2.0. For the Swagger 1.2 compatible version, see the 2.0.0 branch.

swaggerize-express is a design-driven approach to building RESTful apis with Swagger and Express.

swaggerize-express provides the following features:

  • API schema validation.
  • Routes based on the Swagger document.
  • API documentation route.
  • Input validation.

See also:

There are already a number of modules that help build RESTful APIs for node with swagger. However, these modules tend to focus on building the documentation or specification as a side effect of writing the application business logic.

swaggerize-express begins with the swagger document first. This facilitates writing APIs that are easier to design, review, and test.

This guide will let you go from an api.json to a service project in no time flat.

First install generator-swaggerize (and yo if you haven't already):

$ npm install -g yo
$ npm install -g generator-swaggerize

Now run the generator.

$ mkdir petstore && cd $_
$ yo swaggerize

Follow the prompts (note: make sure to choose express as your framework choice).

When asked for a swagger document, you can try this one:

https://raw.githubusercontent.com/wordnik/swagger-spec/master/examples/v2.0/json/petstore.json

You now have a working api and can use something like Swagger UI to explore it.

var swaggerize = require('swaggerize-express');
 
app.use(swaggerize({
    api: require('./api.json'),
    docspath: '/api-docs',
    handlers: './handlers'
}));

Options:

  • api - a valid Swagger 2.0 document.
  • docspath - the path to expose api docs for swagger-ui, etc. Defaults to /.
  • handlers - either a directory structure for route handlers or a premade object (see Handlers Object below).

The base url for the api can also be updated via the setHost function on the middleware.

Example:

var http = require('http');
var express = require('express');
var swaggerize = require('swaggerize-express');
 
app = express();
 
var server = http.createServer(app);
 
app.use(swaggerize({
    api: require('./api.json'),
    docspath: '/api-docs',
    handlers: './handlers'
});
 
server.listen(port, 'localhost', function () {
    app.setHost(server.address().address + ':' + server.address().port);
});

Api path values will be prefixed with the swagger document's basePath value.

The options.handlers option specifies a directory to scan for handlers. These handlers are bound to the api paths defined in the swagger document.

handlers
  |--foo
  |    |--bar.js
  |--foo.js
  |--baz.js

Will route as:

foo.js => /foo
foo/bar.js => /foo/bar
baz.js => /baz

The file and directory names in the handlers directory can also represent path parameters.

For example, to represent the path /users/{id}:

handlers
  |--users
  |    |--{id}.js

This works with directory names as well:

handlers
  |--users
  |    |--{id}.js
  |    |--{id}
  |        |--foo.js

To represent /users/{id}/foo.

Each provided javascript file should export an object containing functions with HTTP verbs as keys.

Example:

module.exports = {
    getfunction (reqres) { ... },
    putfunction (reqres) { ... },
    ...
}

Handlers can also specify middleware chains by providing an array of handler functions under the verb:

module.exports = {
    get: [
        function m1(reqresnext) { ... },
        function m2(reqresnext) { ... },
        function handler(reqres)  { ... }
    ],
    ...
}

The directory generation will yield this object, but it can be provided directly as options.handlers.

Note that if you are programatically constructing a handlers obj this way, you must namespace HTTP verbs with $ to avoid conflicts with path names. These keys should also be lowercase.

Example:

{
    'foo': {
        '$get'function (reqres) { ... },
        'bar': {
            '$get'function (reqres) { ... },
            '$post'function (reqres) { ... }
        }
    }
    ...
}

Handler keys in files do not have to be namespaced in this way.