NodeJS/Express API 版本控制

6
我想建立一个API版本控制,类似于Stripe的做法,但我不太确定如何让express做我需要的事情。https://stripe.com/docs/api#versioning 我要找的是,正确的路由应该是这样的:
/api/v1/call
问题是,我希望他们能像Stripe一样传递版本修订号,因此,如果他们发送了一个标题,如“API-Version: 2015-08-15”,它将映射到该特定版本的主版本。所以,v1但版本更新在2015-08-15。
本质上,如果有一个对API调用的更新不向后兼容,我将为该特定调用滚动一个新版本。Express将聪明地知道,如果没有传递版本,使用最新版本。如果传递了版本,对于每个调用,使用最新版本直到版本日期。
我认为目录结构应该是这样的:
/router/ /router/v1 /router/v1/call /router/v1/anotherCall

也许在调用目录中,有一个索引检查头版本并使用正确的文件。

例如:

  • /router/v1/call/index.js
  • /router/v1/call/20150810.js -- 第一个版本
  • /router/v1/call/20150815.js -- 不向后兼容的更新版本

你有什么想法?

4个回答

5
如果你在路由(url)中管理版本,并且客户端发送的版本号在头文件中,那么Express没有提供任何优雅的方式来处理版本控制。而且,在路由中进行版本控制也不符合RESTful风格。 我编写了一个简单的npm模块来解决这个问题。 https://www.npmjs.com/package/express-routes-versioning Express路由版本化 该模块允许单独对每个路由进行版本管理。它对特定版本策略持中立态度,允许应用程序设置版本,因此您应该能够从标题中解析出版本并将其设置为中间件中的req.version。它支持semver版本控制格式和符号映射多个版本到单个函数。以下是它的工作示例:
var app = require('express')();
var versionRoutes = require('express-routes-versioning')();
app.listen(3000);
app.use(function(req, res, next) {
    //req.version is used to determine the version
   req.version = req.headers['accept-version'];
   next();
});
app.get('/users', versionRoutes({
   "1.0.0": respondV1, 
   "~2.2.1": respondV2
}));

// curl -s -H 'accept-version: 1.0.0' localhost:3000/users
// 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/users
//Anything from 2.2.0 to 2.2.9
function respondV2(req, res, next) {
   res.status(200).send('ok v2');
}

默认情况下,如果客户端版本与服务器提供的版本不匹配,则模块将提供该路由中可用的最新版本回调。可以通过提供额外的回调来覆盖此行为。有关更多信息和源代码,请参见https://github.com/Prasanna-sr/express-routes-versioning


我能否使用变量来代替写版本号,例如 let v = "~1.0.0"?0 - 这种方法行不通。 - Fadi

3
这是我处理版本控制的方法。基本上,您需要创建一个新的router对象,并使用app.use来使只有/api/v1路由被发送到该对象。然后,我使用了一个“落空”路由,它会捕获任何未匹配的内容并返回一个未知命令消息。我还重命名了res.json函数,以便我可以在每个发送出去的对象中添加APIversion = 1(这在router.use函数调用中)。当我有一个v2 api时,我会做同样的事情,但创建一个新文件并使用不同的app.use路径。请参见下面的代码:

app.js

....
app.use('/api/v1', require('./api1.js'));
....

api1.js

var express = require('express');
var router = express.Router();

router.use(function (req, res, next) {
    res._json = res.json;
    res.json = function json(obj) {
        obj.APIversion = 1;
        res._json(obj);
    };
    next();
});

/* ADD ALL YOUR ROUTES HERE */

//Done - catch all - return command failed
router.get('*', function (req, res) {
    res.status = 404;
    res.json({
        success: false,
        message: 'Unknown command'
    });
});

module.exports = router;

1

https://medium.com/@vgjohn/node-js-api-versioning-with-totoro-node-c2ea1ef3dfba

有一个名为totoro-node的小型包,可帮助处理API版本控制中的路由管理。它可能有助于解决您面临的一些问题。您只需编写一个简单的API定义,就可以控制要弃用或继承到后续API版本的哪些端点或API版本。https://www.npmjs.com/package/totoro-node
var app = express()

app.use('/api', totoro.rain({
    v1: {
        "/oAuth": {
            method: "GET",
            deprecated: true,
            endpointImplementation: routes.authRoutes.oAuth
        },
        "/ssoToken": {
            method: "GET",
            endpointImplementation: routes.authRoutes.sso
        }
    },
    v2: {
        "/ssoToken": {
            method: "GET",
            endpointImplementation: routes.authRoutes.sso
        }
    }
}))

0

我认为你可以在所有路由之前设置一个中间件来检查头部信息。

app.use("*",function (req,res,next) {
  var headers = req.headers
  //Process 
  req.apiVersion = "version"
  next()
}
//all your routes

这是一个例子,但你可以在路由器实例中操作头信息,然后将req传递到其他路由

//v1/call/index.js
//all your routes
app.use("/v1/call",function (req,res){
   var version = req.apiVersion;
   //execute something depending on version

})

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接