Express 的 API 版本控制

上一篇博文中,我们介绍了一下后端做 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 啦,版本号的匹配规则啦。