RESTful API

RESTful API

项目中,经常要提供一个 API 供第三方使用,一个通用的 API 设计规范就是使用 RESTful API,RESTful API 是使用 HTTP 中的请求类型来标识对资源的操作。如:

  • GET /ticket 获取 ticket 列表

创建 RESTful Controller

可以通过 -r 参数来创建 REST Controller。如:

thinkjs controller user -r

会创建下面几个文件:

create : src/controller/rest.js create : src/controller/user.js create : src/logic/user.js

其中 src/controller/user.js 会继承 src/controller/rest.js 类,rest.js 是 RESTful Controller 的基类,具体的逻辑可以根据项目情况进行修改。

添加自定义路由

RESTful Controller 创建后并不能立即对其访问,需要添加对应的自定义路由,修改路由配置文件 src/config/router.js,添加如下的配置:

module.exports = [ [/\/user(?:\/(\d+))?/, 'user?id=:1', 'rest'], // 第一种方式 ['/user/:id?', '/user', 'rest'], // 第二种方式 ['/user/:id?', 'rest'], // 第三种方式 ]

注:第三种方式需要 think-router 的版本 >=1.0.17。

上面自定义路由的含义为:

  • /\/user(?:\/(\d+))?/ URL 的正则

通过自定义路由,将 /user/:id 相关的请求指定为 REST Controller,然后就可以对其访问了。

  • GET /user 获取用户列表,执行 getAction

如果有一系列路由都是 RESTful 路由的话,每次都添加自定义路由势必有些麻烦,这时候可以修改一下自定义路由的配置文件,例如:

module.exports = [ [/\/api\/(\w+)(?:\/(\d+))?/, 'api/:1?id=:2', 'rest'] ];

这样表示所有以 /api 开头的二级路由都会被指定成 RESTful 路由。

数据校验

Controller 里的方法执行时并不会对传递过来的数据进行校验,数据校验可以放在 Logic 里处理,文件为 src/logic/user.js,具体的 Action 与 Controller 里一一对应。具体的使用方式请见 Logic。

子级 RESTful API

有时候有子级 RESTful API,如:某篇文章的评论接口,这时候可以通过下面的自定义路由完成:

module.exports = [ [/\/post\/(\d+)\/comments(?:\/(\d+))?/, 'comment?postId=:1&id=:2', 'rest'] ]

这样在对应的 Action 里,可以通过 this.get("postId") 来获取文章的 id,然后放在过滤条件里处理即可。

const Rest = require('./rest.js' module.exports = class extends Rest { async getAction() { const postId = this.get('postId' const commentId = this.get('id' const comment = this.model('comment' if(commentId) { // 获取单条评论的详细信息 const data = await comment.where{post_id: postId, id: commentId}).find( return this.success(data } else { // 获取单条文章下的评论列表 const list = await comment.where{post_id: postId}).select( return this.success(list } } }

多版本 RESTful API

有些 REST API 有时候前后不能完全兼容,需要有多个版本,这时候也可以通过自定义路由管理,如:

module.exports = [ [/\/v1\/user(?:\/(\d+))?/, 'v1/user?id=:1', 'rest'], //v1 版本 [/\/v2\/user(?:\/(\d+))?/, 'v2/user?id=:1', 'rest'] //v2 版本 ]

这时候只要在 src/controller/ 下建立子目录 v1/v2/ 即可,执行时会自动查找,具体见 多级控制器。

Mongo 的 RESTful API

由于 Mongo 的 id 并不是纯数字的,所以处理 Mongo 的 RESTful API 时只需要修改下对应的正则即可(将 \d 改为 \w):

module.exports = [ [/\/user(?:\/(\w+))?/, 'user?id=:1', 'rest'] ]

常见问题

怎么查看 RESTful API 的自定义路由已经生效?

有时候添加 RESTful Controller 和自定义路由后,访问并没有生效,这时候可以通过 DEBUG=think-router npm start 启动服务查看解析后的 controller 和 action 看其是否生效,具体请见怎么查看当前地址解析后的 controller 和 action 分别对应什么?