在使用的过程中我又发现了另一个更加好用的轮子 express-swagger-generator,这个轮子的配置更简单,使用也更加的方便,接下来就简单的介绍一下,之前的配置方式在下面:
引入 express-swagger-generator
安装
yarn add express-swagger-generator
app.js 中引用
const express = require('express');
const app = express();
const expressSwagger = require('express-swagger-generator')(app);
let options = {
swaggerDefinition: {
info: {
description: 'This is a sample server',
title: 'Swagger',
version: '1.0.0',
},
host: 'localhost:3000',
basePath: '/v1',
produces: [
"application/json",
"application/xml"
],
schemes: ['http', 'https'],
securityDefinitions: {
JWT: {
type: 'apiKey',
in: 'header',
name: 'Authorization',
description: "",
}
}
},
basedir: __dirname, //app absolute path
files: ['./routes/**/*.js'] //Path to the API handle folder
};
expressSwagger(options)
app.listen(3000);
观察可以发现这个包的配置文件和swagger-ui
的是很像的,所以可以很轻松的进行迁移,并且集成完成后就可以用更简单的jsdoc
来描述接口了,这可比写yaml格式的注释不知道高到哪里去了:
/**
* This function comment is parsed by doctrine
* @route GET /api
* @group foo - Operations about user
* @param {string} email.query.required - username or email - eg: user@domain
* @param {string} password.query.required - user's password.
* @returns {object} 200 - An array of user info
* @returns {Error} default - Unexpected error
*/
exports.foo = function() {}
- 大体的用法可以参考这里 express-template - usage.md
- 这个包的github上也有提到更详细的介绍 express-swagger-generator - README
以下为原文:
express 作为一个 node 服务端框架,当然少不了各种的接口,我之前的项目都是通过 jdoc 样式来说明接口,但是这样的表达能力依旧略显单薄,所以这里就记录下如何在 express 框架里集成大名鼎鼎的 swagger 来规范化后端接口:
使用 jdoc 说明接口
/**
* 设置活动状态
*
* @param {String} activityId 活动ID
*
* @memberof activity
*/
router.post('/setActivityNextState', (req, res) => {
...
})
使用 swagger 说明接口
接入过程
想在 express 里接入 swagger 需要两个包swagger-jsdoc
和swagger-ui-express
,前者将 jsdoc 格式的注释转化为 swagger 类型的 json,后者使用这个 json 生产对应的 swagger 页面,所以说,接入成功之后我们给接口写的 jsdoc 注释就会自动生成为 swagger 文档页面。
安装
yarn
yarn add swagger-jsdoc swagger-ui-express
npm
npm install swagger-jsdoc swagger-ui-express --save
引入
首先打开app.js
,在let app = express()
下面加上这一段代码
import swaggerUi from 'swagger-ui-express'
import swaggerJSDoc from 'swagger-jsdoc'
import path from 'path'
// 配置 swagger-jsdoc
const options = {
definition: {
// swagger 采用的 openapi 版本 不用改
openapi: '3.0.0',
// swagger 页面基本信息 自由发挥
info: {
title: 'Express Template',
version: '1.0.0',
}
},
// 重点,指定 swagger-jsdoc 去哪个路由下收集 swagger 注释
apis: [ path.join(__dirname, '/router/*.js') ]
}
const swaggerSpec = swaggerJSDoc(options)
// 开放 swagger 相关接口,
app.get('/swagger.json', function(req, res) {
res.setHeader('Content-Type', 'application/json');
res.send(swaggerSpec);
});
// 使用 swaggerSpec 生成 swagger 文档页面,并开放在指定路由
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec));
注意,这段代码里使用了import / from
,请确保你的项目引入了babel
等语法编译器。其中最后一行代码,那里指定了你 swagger 文档页面的路由,这时候启动项目然后访问 localhost:3000/api-docs/ 就可以看到 swagger 页面了。
给接口写文档
如果上一步你已经完成的话就说明已经集成成功了,接下来就是给每个接口写对应的 swagger 文档,格式如下:
/**
* @swagger
* /hello:
* get:
* tags:
* - 测试
* summary: GET 测试
* description: 用于测试基础 GET 请求的接口
* responses:
* 200:
* description: 【成功】 返回 world
*/
router.get('/hello', (req, res) => {
res.send('world')
})
找到你的接口,在它上面 @swagger
之后,这一块的注释就会被swagger-jsdoc
找到并解析成对应的 yaml 文档,标准的 swagger 文档使用 yaml 格式书写。这里推荐一个 在线 swagger 编辑器。
在你完成了上面的工作之后重启 express 服务就可以在 localhost:3000/api-docs/ 路由下看到你刚才写的接口了。等一下,你说你的 swagger 里还是啥都没有?看下一节。
找不到接口文档
如果你可以打开 swagger 页面,但是在接口上面无论怎么写它都不会同步到 swagger 页面里,那么就有可能是刚才app.js
里options.apis
这个属性的配置出现了问题,swagger-jsdoc
服务就是根据这个属性来寻找你的接口所在文件的,这里最好使用path.join()
来明确路由,js 里直接写的相对路由很坑的,只要这里生成的绝对路径可以正确指向你的路由接口所在文件,那么这个问题就自然的解决了。
封装
如果你觉得把所有的代码都写到app.js
里很丑陋的话,那么恭喜你,这一小节就是为你准备的,如果你喜欢到处封装的话,那你肯定有一个config.js
文件,在加上我们要封装出的swagger
文件和app.js
,这三个的目录关系如下:
app.js ------------ 项目入口
config.js --------- 静态配置文件
/swagger
├── index.js ------ swagger封装文件
为啥要给swagger
多建一层目录,我也不知道,担心以后会有 swagger 相关的文件出现,到时候就可以直接放在这个目录下。下面是具体的代码和说明:
swagger/index.js
这里引入了两个需要的包,并从config.js
中获取配置,这一块的主要内容就是文章开头的代码修改了其中的静态配置项,并封装为一个用于设置 swagger 的方法
import swaggerUi from 'swagger-ui-express'
import swaggerJSDoc from 'swagger-jsdoc'
import { swaggerConfig } from '../config'
export default function setSwagger(app) {
const options = {
definition: {
openapi: swaggerConfig.openapi,
info: {
title: swaggerConfig.title,
version: swaggerConfig.version
}
},
apis: swaggerConfig.apis
}
const swaggerSpec = swaggerJSDoc(options)
app.get('/api-docs.json', (req, res) => {
res.setHeader('Content-Type', 'application/json')
res.send(swaggerSpec)
})
app.use(swaggerConfig.routerPath, swaggerUi.serve, swaggerUi.setup(swaggerSpec))
}
config.js
这里引入了path
模块,注意其中的apis
属性可能会因为你项目里app.js
和config.js
的路径不同而发生变化
import path from 'path'
// swagger配置信息
export const swaggerConfig = {
openapi: '3.0.0',
title: 'Express Template',
version: '1.0.0',
apis: [
path.join(__dirname, '/router/*.js')
],
routerPath: '/api-docs'
}
app.js
封装好后直接引入对应方法,并把app
当做参数传过去即可
// 引入swagger
import setSwagger from './swagger'
setSwagger(app)