【已过时】Express中使用swagger设计RestfulAPI

这文章好久前写的了,后来弄API不这么干了,各位看个乐呵就好~


开始的时候只是单纯的想写API文档给自己看着方便,然后就发现了这个大坑。才接触没几天,记一下自己的理解吧。关于swagger和貌似已经年久失修不知道还能坚持多久的swagger-tools

这不是一个手把手教学,只给了思路,伸手党失望了

对我来说Swagger是什么

这是一个关于API设计的流程吧。首先定义API的样子,有哪些接口接收什么数据返回什么数据身份怎么验证。然后根据API定义自动生成代码和路由。然后自己实现API的具体接口函数。最后用API的定义测试完成效果。这里一步步讲吧

设计API

Swagger有个吊炸天的应用叫Swagger Editor,有在线版本,还有一个很好的DEMO。里面用他独有的语言定义了API,语法很简单,对着样例抄一会儿就会了,如果实在不行官方文档也有很好的例子。格式可以用OpenAPI 2或者OpenAPI 3。兼容原因我最后用了二,具体的后面再说,要不是兼容性感觉OA3更好一些,OA3有一个OneOf的功能很好用,可以让一个接口返回(或者接收)某几种数据(或者参数)。

设计好了之后可以在编辑器里面下载为json或者yaml格式,我这里使用的是json。这就是我们最终要实现的API接口定义。

值得注意的是在这里我的验证方式有两种

  • Basic Auth:传统的用户名密码
  • Bearer JsonWebToken:就叫它JWT吧

在设计的使用Basic Auth就选basic类型的就可以,JWT的需要选择api key类型,然后在测试的时候自己用Bearer <JWT>代替就可以了。

自动生成代码和路由

这里用到了一个工具swagger-tools简直是神器。简单解释下为什么是神器。一般的API实现需要我们自己搞定路由,然后验证接收到的数据是不是符合接口定义,然后才能写业务逻辑。有很大一部分时间都浪费在了搞定路由和验证数据上。而swagger-tools的作用就是读取API设计文档,然后自动创建路由表自动验证数据,我们只需要提供自己的业务逻辑就好了。

使用方法见文档。摘抄一部分关键代码在这里。记住第三行的这个controllers,这是问题的关键!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// swaggerRouter configuration
var options = {
controllers: './controllers',
useStubs: process.env.NODE_ENV === 'development' ? true : false // Conditionally turn on stubs (mock mode)
};

// The Swagger document (require it, build it programmatically, fetch it from a URL, ...)
var swaggerDoc = require('./api/swagger.json');

// Initialize the Swagger middleware
swaggerTools.initializeMiddleware(swaggerDoc, function (middleware) {
// Interpret Swagger resources and attach metadata to request - must be first in swagger-tools middleware chain
app.use(middleware.swaggerMetadata());

// Validate Swagger requests
app.use(middleware.swaggerValidator());

// Route validated requests to appropriate controller
app.use(middleware.swaggerRouter(options));

// Serve the Swagger documents and Swagger UI
app.use(middleware.swaggerUi());

// Start the server
http.createServer(app).listen(serverPort, function () {
console.log('Your server is listening on port %d (http://localhost:%d)', serverPort, serverPort);
});
});

实现业务逻辑

具体怎么实现就看自己需求了,每个项目不一样。这里说的是怎么把业务逻辑的代码和swagger-tools连接起来。我们捋一下请求来了之后都会干什么。

  1. 收到一个请求,swagger-tools(下面简称ST)根据API设计文档查看这个请求属于哪个路由
  2. 根据API设计文档验证请求是否合法,结构是否正确,如果不是就抛出相应的异常。
  3. 根据定义进行身份验证
  4. 根据路由调用相应的业务逻辑。

ST怎么知道该调用哪个函数?

如果刚才有仔细看API文档的话应该发现,文档里面并没有关于业务逻辑的函数的内容,仅仅是关于API的。但是这肯定是需要定义的,文档中就告诉我们了需要根据配置文件(刚才提到的哪个controllers)找到业务逻辑的文件,然后再根据x-swagger-router-controller找到对应的文件,然后根据operationId调用对应的函数处理。

此外,身份认证的部分在Swagger Security这里,也是需要给定名称和对应函数。但是这里有个问题。之前我们在中间件处理的时候可以收到(err,req,res,next)的参数列表,可以直接res.send()来返回数据,但是这里的参数列表却是(req, authOrSecDef, scopesOrApiKey, callback)。没有res?那怎么返回?

方法就是自己新建一个异常,然后给callback就好了,像这样,然后再在后面检测异常再返回

1
2
3
var err = new Error('Failed to authenticate using bearer token');
err['statusCode'] = 403; // custom error code
callback(err);

测试

还有个神器就是swagger UI,是一个,自己看吧,可以看API还可以直接测试请求,直接把git仓库里的dist文件夹代码拿来用就是个现成的,只需要改一下文件内的swagger.json目录就可以,也就是你的API设计文档(对的JSON没看错)。然后不要用ST提供的swagger UI,那个没法发带验证的请求,我不知道是我配置问题还是什么问题。

总结

目前看的话还算够用,但是也没接触过这方面内容,不知道这个年久失修的库还能用多久,也不知道其他人怎么弄的,欸