上一篇博文中,我们介绍了一下后端做 API 版本控制的几种方法。

最近在用 Node.js 做一个小项目 DayCache,其中就涉及到了给客户端提供 API 调用这一块,当然就也需要 API 的版本控制了。

/api/v1/post/:id

1
2
3
4
5
// Version 1
@GET /api/v1/post/:id
// Version 2
@GET /api/v2/post/:id

对于这种方式的 API 版本控制我们应该怎么实现呢?

首先,把目录结构组织如下,

1
2
3
4
5
6
├── api
│   └── v1
│   └── index.js
│   └── signin.js
│   └── signup.js
└── index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// index.js
...
/*
// API
如果需要新增加一个 API 的版本
1. 把 ./api/v1 目录复制一份,改名为 v2
2. 在下面的 API_VERSIONS 字典中加入一对 kv,如 `'Version 2': '/v2'`
*/
var API_VERSIONS = {
'Version 1': '/v1'
}
for (var v in API_VERSIONS) {
var api = require('./api' + API_VERSIONS[v]);
api(app);
}
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// api/v1/index.js
// 如果需要加入新的请求路径,只需要在下面加入路径
// 然后在 `api/v1` 下建立同名文件即可
let ROUTE_PATHS = [
'/signin',
'/signup',
];
module.exports = function (app) {
for (let i in ROUTE_PATHS) {
let path = ROUTE_PATHS[i];
console.log(path);
app.use('/api/v1' + path, require('.' + path));
}
};

这样,API 版本化的工作就已经完成了,而且不同版本的 API 拆分地比较干净,同一个版本不同路径的请求也都在不同的文件中。

Accept-Version: 1.0

对于这种请求的 API 版本放到 header 中的,也比较好处理,可以看一下 express-routes-versioning 这个中间件(毕竟 Express.js,中间件就是多),它就是比较优雅地处理了这个问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// index.js
var app = require('express')();
var routesVersioning = require('express-routes-versioning')();
app.get('/test', routesVersioning({
"1.0.0": respondV1,
"~2.2.1": respondV2
}));
// curl -s -H 'accept-version: 1.0.0' localhost:3000/test
// version 1.0.0 or 1.0 or 1 !
function respondV1(req, res, next) {
res.status(200).send('ok v1');
}
//curl -s -H 'accept-version: 2.2.0' localhost:3000/test
//Anything from 2.2.0 to 2.2.9
function respondV2(req, res, next) {
res.status(200).send('ok v2');
}

把请求 header 中 Accept-Version 不同的 API 版本挂在到不同的 handler 中,而且还可以使用类似于 ~2.2.1 的方式指定版本号。
这个中间件的代码没有多少,可以根据你的需要定制一个,比如 custom header 啦,版本号的匹配规则啦。