API versioning in Express.js
在上一篇博文中,我们介绍了一下后端做 API 版本控制的几种方法。
最近在用 Node.js 做一个小项目 DayCache,其中就涉及到了给客户端提供 API 调用这一块,当然就也需要 API 的版本控制了。
/api/v1/post/:id
// Version 1
@GET /api/v1/post/:id
// Version 2
@GET /api/v2/post/:id
对于这种方式的 API 版本控制我们应该怎么实现呢?
首先,把目录结构组织如下,
├── api
│ └── v1
│ └── index.js
│ └── signin.js
│ └── signup.js
└── index.js
// 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);
}
...
// 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,中间件就是多),它就是比较优雅地处理了这个问题:
// 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 啦,版本号的匹配规则啦。