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 啦,版本号的匹配规则啦。

© Xinyu 2014 - 2024