I have used markdown and wiki to manage api doc, from which I have suffered a lot. It wastes too much time and is very boring. The docuement should be repaired when you change the api. It's very unconvenient to test and debug. The management of api doc totally depends on people. As a result, it is hard to make docuement have high quality. Meanwhile, the developers will spend more time on testing, which may have a bad effect on project. What's worse, it will affect our mood, which is unbearable for me : (.
So I try my best to solve this problem. When there is a will, there is a way. Finally, I find The OpenAPI Specification. And it's ecological circle is perfect. Swagger includes lots of tool chain. According to the Specification, Swagger UI can produce the docuement. The data types and models of OpenAPI are based on the JSON-Schema Draft 4.
I truly hope that this library can help those who are in the same trouble. Happy coding.
BTW,PR & Issue & Star are welcome! : )
- Koa-OAI-Router
- Features
- Installation
- Quick Start
- Advanced
- Plan
- Built-in Swagger-UI, easy view and debug
- Auto generate route by OpenAPI/Swagger api doc, and validate parameters
- Support OpenAPI/Swagger2.0 Specification with yaml or json file
- Support Json Schema v4, validate query,body,path,header
- Support custom Json Schema format
- Support custom error handler
For koa@>=2.x (next):
npm install koa-oai-router@next --save
For koa@<2.x:
Not Support Yet!
If you not know how to do this. please read OpenAPI first.
# api/api.yaml
swagger: '2.0'
info:
version: 1.0.0
title: koa-oai-router
consumes:
- application/json
produces:
- application/json
basePath: /api
paths:
/people:
get:
tags:
- People
description: find a people by name or mobile
x-oai-controller:
- file: people
handler: get
parameters:
- name: name
in: query
type: string
- name: mobile
in: query
type: string
responses:
200:
description: people's info
schema:
$ref: '#/definitions/People'
default:
description: unexpected error
schema:
$ref: '#/definitions/Error'
post:
tags:
- People
description: input a people's info
x-oai-controller:
- file: people
handler: post
parameters:
- name: body
in: body
required: true
schema:
$ref: '#/definitions/People'
responses:
200:
description: people's info
schema:
$ref: '#/definitions/People'
default:
description: unexpected error
schema:
$ref: '#/definitions/Error'
definitions:
People:
type: object
required:
- name
- sex
- height
- weight
properties:
name:
type: string
sex:
type: string
enum:
- male
- female
height:
type: integer
format: int32
minimum: 10
maximum: 1000
weight:
type: number
format: float
minimum: 50
maximum: 200
mobile:
type: string
Error:
title: Error
type: object
required:
- status
- error
properties:
status:
type: integer
path:
type: string
error:
type: string
detail:
type: object
do your staff code
// controllers/people.js
var people = {name: 'BiteBit'};
function get(ctx, next) {
ctx.body = people;
}
function post(ctx, next) {
people = ctx.request.body;
ctx.body = people;
}
module.exports = {
get: get,
post: post
};
// app.js
import Koa from ('koa');
import bodyParser from ('koa-bodyparser');
import Router from ('koa-oai-router');
const app = new Koa();
const server = app.listen(9000);
app.use(bodyParser());
// set koa-oai-router options
var opt = {
// path of api doc
apiDoc: './api/api.yaml',
// dir of controllers
controllerDir: './controllers',
// get listening port from server
server: server,
// add major version to api prefix
versioning: true,
// show api-explorer
apiExplorerVisible: true
};
var router = new Router(opt);
// mount routes in api doc
app.use(router.routes());
// mount api-explorer
app.use(router.apiExplorer());
open http://127.0.0.1:9000/api-explorer with browser,enjoy it!
string required
Api doc's path, support OpenAPI2.0 json,yaml.
string required
Dir of controllers, it's used when set file and handler of a api.
number optional default 80
The port is koa server listening, used to be log out api-explorer url.
net.Socket optional
The Socket is koa serving, which will find serving port automatically. No need to set port and server together.
string optional default is ajv
You can choice ajv, tv4 or null. I'm still finding a perfect Json Schema validator.
- ajv Best performance in Benchmark , support data type coercion, this feature is very suit for query parameters, because querystring always pase json value as string. But at this moment, It is not support add custom format to other data type, except string.
- tv4 Not support data type coercion, but support add custom fromat to all data type.
- null Not use parameter validator.
boolean optional default true
Add the major version of api doc to the api endpoint. You also can use basePath to manage the api.
boolean optional default true
Show api-explorer. Showing on production is not recommended.
string optional default /api-explorer
The path of api-explorer.
string optional default*/koa-oai-router*
Static file path of swagger-ui is only set when your static file path is /koa-oai-router.
object optional default {}
You can add custom format validation through this.
Key in object is the format keyword.
Value in object must be a function with parameters data and schema.
- data filed to validate
- schema
When it is valid you should return null. When it is invalid you should return error string.
Return what kind of result depends on which validator you choice.
- ajv if valid return true, otherwise return false.
- tv4 if valid return null, otherwise return error message string.
import Koa from ('koa');
import bodyParser from ('koa-bodyparser');
import Router from ('koa-oai-router');
const app = new Koa();
const server= app.listen(9000);
app.use(bodyParser());
var opt = {
apiDoc: './api/api.yaml',
controllerDir: './controllers',
server: server
jsonSchemaFormatters: {
"zh-CN": (data, schema)=> {
return data !== 'zh-CN' ? null : 'language is not zh-CN';
}
}
};
const router = new Router(opt);
app.use(router.routes());
app.use(router.apiExplorer());
function optional default error handler
You can design your custom error handler by doing this. The function has parameters error, ctx, schema. The returned value is response to the reqeust.
- error Error, created by http-errors. if HTTP status code is 400, the error will have extra keywords below.
- type string invalid parameter type, header, path, query, body
- path string invalid parameter's path
- error string invalid message
- data object data been validated
- detail object the original error
- ctx koa ctx
- schema Json Schema of the api
Define default response schemas, if you don't want to write response schema under every api.
const commonSchema = {
type: 'object',
properties: {
error_code: {
type: 'number',
},
error_description: {
type: 'string',
},
},
};
const schemas = {
401: {
title: 'Unauthorized',
schema: commonSchema,
},
402: {
title: 'PaymentRequired',
schema: commonSchema,
},
403: {
title: 'Forbidden',
schema: commonSchema,
},
404: {
title: 'NotFound',
schema: commonSchema,
},
429: {
title: 'TooManyRequests',
schema: commonSchema,
},
500: {
title: 'InternalError',
schema: commonSchema,
},
};
Return router middleware which dispatches a route matching the request.
Return router middleware which mounts swagger-ui 2.x. Open /api-explorer to explorer you api.
Return router middleware which mounts swagger-ui 3.x. Open /api-explorer-v3 to explorer you api. swagger-ui 3.x supports 2.x specification.
Through this, you can extend plugin to handle options which starts with x-oai- in apiDoc.
- keyword starts with x-oai- , not including x-oai-controller.
- fn is handler of keywords.
For example,we need to configure cache expired time for api through apiDoc. We can extend plugin based on following steps.
# First,configure cache expired time at apiDoc.
# x-oai-cache:
# expire: 86400
# api.yaml
/users/{userId}:
get:
tags:
- User
description: find a user by userId
x-oai-cache:
expire: 86400
x-oai-controller:
- file: people
handler: get
parameters:
- name: userId
in: path
required: true
type: number
responses:
default:
description: unexpected error
schema:
$ref: '#/definitions/Error'
/*
* Second,develop x-oai-cahce plugin.
* Export a function with a argument, and return a koa middleware.
*/
export default (config) => {
// config is {expire: 86400}
return (ctx, next) => {
// write your code.
}
}
/*
* Third,mount your plugin to router with keyword.
*/
var router = new Router(opt);
var cachePlugin = new Cache({
store: new Redis()
});
router.use('x-oai-cache', cachePlugin);
app.use(router.routes());
app.use(router.apiExplorer());
TODO
koa-oai-router enlarges OpenAPI, now we will recognize x-oai-controller keyword in all method.
x-oai-controller is an object array and every element must include file and handler.
Handler will be executed from up to down, if you have multi handlers. Eg, acl.isAdmin will be executed before people.get
paths:
/people:
get:
tags:
- People
description: find a people by name or mobile
x-oai-controller:
- file: acl
handler: isAdmin
- file: people
handler: get
The controller's file path was related to controllerDir.
The function is exported from the file. The following functions are same to koa@next.
- support common function
- support async function
- support generator function
Validation is based on JSON-Schema Draft 4, and it enlarges some OpenAPI's format, like int32,int64,float,double.
At this moment query, body, path and header is supported. The validate order is header -> path -> query -> body. Any step validate failed will throw HTTP 400 error and response error message.
Recommended Reading:
Validate the header of request.
paths:
/users:
get:
summary: List all users
parameters:
- name: token
in: header
description: token to be passed as a header
required: true
type: string
Validate the path, multi path parameters are supported. If peopleId is missing, the route will not be macthed. At this moment, validation of path only support data type and format.
Notice: Path parameter syntax in OpenAPI is "{pathId}".
paths:
/user/{peopleId}:
get:
summary: pet
parameters:
- name: peopleId
in: path
description: peopleId'id
required: true
type: string
Validate query parameter. Multi query parameters are supported.
paths:
/users:
get:
summary: find a user by name
parameters:
- name: name
in: query
description: name of user
required: true
type: string
Validate body parameter, the id and name are required.
NOTICE: OpenAPI2.0 Specification only supports one request body. If a api has multi body, the first body will be validated.
paths:
/user:
post:
summary: add user
parameters:
- name: user
in: body
description: user to add to the system
required: true
schema:
$ref: '#/definitions/User'
definitions:
User:
required:
- id
- name
properties:
id:
type: integer
format: int64
name:
type: string
tag:
type: string
If the default error handler is not fit you, you can design your custom error handler. The default error handler will get the response's schema by HTTP status code(if not, using default). Then it will pick schema's properties from the error.
swagger: '2.0'
info:
version: 1.0.0
title: koa-oai-router
consumes:
- application/json
produces:
- application/json
basePath: /api
paths:
/user:
get:
x-oai-controller:
- file: people
handler: get
parameters:
- name: name
in: query
type: string
required: true
responses:
200:
description: user's info
schema:
$ref: '#/definitions/User'
default:
description: unexpected error
schema:
$ref: '#/definitions/Error'
definitions:
User:
required:
- id
- name
properties:
id:
type: integer
format: int64
name:
type: string
tag:
type: string
Error:
title: Error
type: object
required:
- status
- error
properties:
status:
type: integer
type:
type: string
path:
type: string
error:
type: string
detail:
type: object
When page is not inputed, the api will send HTTP 400 with the response body handled by error handler.
{
"status": 400,
"type": "query",
"path": "",
"error": "Missing required property: page",
"data": {},
"detail": {
"message": "Missing required property: page",
"params": {
"key": "page"
},
"code": 302,
"dataPath": "",
"schemaPath": "/required/0",
"subErrors": null,
"stack": "...."
}
}
- Support OpenAPI/Swagger1.x
- Support OpenAPI/Swagger3.0
- Support OpenAPI/Swagger2.0 Security keyword
- Support Response validate
- Research more Json Schema validator
- More unit test
- Benchmark