Hosted by Three Crickets

Prudence
Scalable REST Platform
For the JVM

Prudence logo: bullfinch in flight

Describing APIs

An important aspect of managing a RESTful API is documenting it. As with any API documentation, it is useful for humans, both users and developers. But it's also useful for consumption by clients, which can use a properly-formatted description to automatically generate calling interfaces for your APIs.
Prudence allows you to annotate your code with special comments from which a description data can be generated. RESTful description blocks in Prudence must be delimited with "/***" and "*/" (triple-asterix comments). This allows the block to be ignored by the programming language, as a regular comment, while differentiating it from code documentation, which is usually delimited using "/**" and "*/" (double-asterix comments, for example see Sincerity's JsDoc plugin). Within these comments, Prudence will look for special annotation tags beginning with "@", similarly to how the JavaDoc specification works. Annotation values can extend across multiple comment lines, and some require special formats, as detailed below.
Even if you don't intend to support a description technology, adhering to such annotation standards is very useful for documenting your URI-space for humans, and course will allow you to easily support such technologies in the future.

Generating Description Data

The "prudence" Sincerity command has a "describe" sub-command that will automatically gather annotations, parse them, and generate description data:
sincerity prudence describe myapp
Syntax errors will be reported if discovered.
By default, description files will be written to the application's "description" subdirectory, but you can also specify a different subdirectory name:
sincerity prudence describe myapp api-docs

Swagger

Prudence supports Swagger (a trademark of Reverb Technologies, Inc.), an emerging standard for RESTful API description with a broad ecosystem of tools and wrappers.
At the very least, you will need a "@swagger" annotation specifying the type for the description block. The documents generated by the "describe" tool are fully-compliant JSON, indented for human readability, with a ".json" extension.
Most annotations match the fields in the Swagger specification, version 1.2, and are explained there. However, Prudence automates many values, and additionally provides sensible defaults.

@swagger info

Provides general information about your API.
You can have multiple "@swagger info" blocks in your application, though the parser will merge them all together. It's good practice to place these blocks in your settings.js, routing.js, or both.
/***
 * RESTful API for My Application.
 *
 * @swagger info
 * @apiVersion 1.0
 * @basePath http://myapp.org/api
 * @title My Application
 * @description This API provides access to
 *              My Application's resources
 * @license GNU Lesser General Public License 3.0
 * @licenseUrl http://www.gnu.org/licenses/lgpl.html
 * @contact info@threecrickets.com
 */
"@swaggerVersion", "@apiVersion" and "@basePath" are used as defaults for the "@swagger api" sections, which you may override there.
Additional annotations will get default values, which you may override:

@swagger api

Represents a group of APIs, often intended to mean a single RESTful resource, though it may be useful to group several resources together in some cases. In Swagger, all APIs within a group are described in a single JSON document.
It's good practice to place these blocks at the top of the source code file for a resource.
/***
 * This resource represents a person in the database. Persons have unique
 * IDs defined by integers.
 *
 * @swagger api
 * @description A person
 * @produces application/json text/plain
 * @consumes application/json text/plain
 */
Values for "@produces" and "@consumes" may be specified in one annotation, or in several:
@produces application/json
@produces text/plain
Additional annotations will get default values, which you may override:

@swagger operation

Represents a single API call, a RESTful verb on a URL. An operation must be associated with a "@swagger api" block, though if one does not exist it will be inferred and generated for you (though without "@description", "@produces", "@consumes", etc.).
It's good practice to place these blocks right before the appropriate handler code.
/***
 * Retrieve a person's data according to its ID.
 *
 * @swagger operation
 * @summary Retrieves a person
 * @notes Accesses the MongoDB database
 * @path /person/{personId}/
 * @method GET
 * @nickname getPerson
 * @parameter path personId string The person's ID
 * @type Person
 * @responseMessage 400 Error Invalid data
 * @responseMessage 404 null Not found
 */
function handleGet(conversation) {
	...
}
The link between a "@swagger operation" and its "@swagger api" is via the "@resourcePath" annotation.
The "@type" annotation matches a "@swagger model" (see below).
You may include none or several "@parameter" annotations, with the following attributes:
  1. The parameter type: "path", "query", "body", "header" or "form"
  2. Name
  3. Type
  4. Optional: description
You may include none or several "@responseMessage" annotations, with the following attributes:
  1. HTTP status code (an integer)
  2. Type: a "@swagger model", or "null" to specify no content
  3. Optional: description
Additional annotations will get default values, which you may override:

@swagger model

Represents a data model. As with "@swagger operation", it is associated with a "@swagger api" block.
/***
 * Person model.
 *
 * @swagger model
 * @id Person
 * @property name string
 * @property lastname string
 */
You may include none or several "@parameter" annotations, with the following attributes:
  1. Name
  2. Type

Serving Swagger

You can serve your Swagger description statically via routing.js:
app.routes = {
	...
	'/api-docs/*': {
		type: 'static',
		root: 'description'
	}
}
However, most Swagger clients will require Cross-Origin Resource Sharing (CORS), which you can support using Prudence's CORS filter:
app.routes = {
	...
	'/api-docs/*': {
		type: 'cors',
		allowOrigin: '*',
		next: {
			type: 'static',
			root: 'description'
		}
	}
}
You can test your Swagger description using the Swagger UI application. A demo is available here.

Working with Swagger Clients

Most Swagger clients will require your API to use Cross-Origin Resource Sharing (CORS), which you can support using Prudence's CORS filter. For example, if you're implementing your API as manual resources, you can just wrap your entire "manual" route type with the filter:
app.routes = {
	...
	'/*': [
		{
			type: 'cors',
			allowOrigin: '*',
			allowMethods: ['GET', 'POST', 'PUT', 'DELETE'],
			allowHeaders: 'Content-Type',
			next: 'manual'
		},
		'templates',
		'static'
	]
}
An additional requirement for CORS is that your resources support the HTTP "OPTIONS" verb. This can be easily done with an empty handler:
function handleOptions(conversation) {
	return null
}
Of course, instead of using the CORS filter, your handlers can actually set the appropriate CORS headers as is appropriate. See custom headers for more information:
function handleOptions(conversation) {
	conversation.responseHeaders.set('Access-Control-Allow-Origin', '*')
	conversation.responseHeaders.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE')
	conversation.responseHeaders.set('Access-Control-Allow-Headers', 'Content-Type')
}

The Prudence Manual is provided for you under the terms of the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. The complete manual is available for download as a PDF.

Download manual as PDF Creative Commons License