简体   繁体   English

NodeJS / Express API版本控制

[英]NodeJS/Express API versioning

I'd like to set up an API versioning, similar to how Stripe does it but I'm not quite sure how to make express do what I need. 我想设置一个API版本控制,类似于Stripe的方式,但是我不太确定如何使express满足我的需要。 https://stripe.com/docs/api#versioning https://stripe.com/docs/api#versioning

What I'm looking for is, the proper route would be something like: 我正在寻找的是正确的路线,例如:

/api/v1/call / API / V1 /通话

The kicker is, I'd like them to pass in a version revision like stripe allows, so if they sent a header like "API-Version: 2015-08-15", it would map to that specific version of the major version. 更重要的是,我希望他们传递类似stripe allow的版本修订,因此,如果他们发送了诸如“ API-Version:2015-08-15”之类的标头,它将映射到主要版本的特定版本。 So, v1 but the version updated on 2015-08-15. 因此,v1的版本已于2015-08-15更新。

Essentially, if there is an update to the API call that is not backwards compatible, I'd roll a new version for that particular call. 本质上,如果API调用的更新不向后兼容,那么我将为该特定调用推出新版本。 Express would be smart enough to know that if a version isn't passed, use the latest. Express足够聪明,可以知道如果未通过版本,请使用最新版本。 If a version is passed, use the latest version for each call up until the version date. 如果通过了版本,则每次调用都使用最新版本,直到版本日期为止。

I'd assume the directory structure would be something like: 我认为目录结构应该是这样的:

  • /router/ /路由器/
  • /router/v1 /路由器/ V1
  • /router/v1/call /路由器/ V1 /通话
  • /router/v1/anotherCall /路由器/ V1 / anotherCall

And maybe in the call directories, there is a index that checks for the header version and uses the proper file. 也许在调用目录中,有一个用于检查标头版本并使用正确文件的索引。

So maybe for instance 所以也许

  • /router/v1/call/index.js /router/v1/call/index.js
  • /router/v1/call/20150810.js -- First version /router/v1/call/20150810.js-第一个版本
  • /router/v1/call/20150815.js -- Updated version that isn't backwards compat. /router/v1/call/20150815.js-更新的版本没有向后兼容。

Thoughts? 思考? Ideas? 想法?

This how I'm handling versioning. 这就是我处理版本控制的方式。 Basically you create a new router object and use app.use so that only /api/v1 routes are sent to it. 基本上,您将创建一个新的router对象并使用app.use以便仅将/api/v1路由发送给它。 I then use a "fall through" route which catches anything which didn't match and returns a unknown command message. 然后,我使用一条“掉线”路由来捕获所有不匹配的内容,并返回未知的命令消息。 I also renamed the res.json function so that I can add APIversion = 1 to each object that went out (That's in the router.use function call). 我还重命名了res.json函数,以便可以向出APIversion = 1每个对象添加APIversion = 1 (即在router.use函数调用中)。

Whenever I have a v2 api I'll do this exact same thing but create a new file and use a different app.use path. 每当我拥有v2 API时,我都会做同样的事情,但是会创建一个新文件并使用不同的app.use路径。 See below: 见下文:

app.js app.js

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

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;

If you are managing version in routes(url) and client sends version in headers then express doesn't provide any elegant way to handle versioning. 如果要在routes(url)中管理版本,并且客户端在标头中发送版本,则express不提供任何优雅的方式来处理版本控制。 Also, doing versioning in routes is not restful. 同样,在路由中进行版本控制也不是一件容易的事。

I wrote an simple npm module to solve this problem. 我编写了一个简单的npm模块来解决此问题。 https://www.npmjs.com/package/express-routes-versioning https://www.npmjs.com/package/express-routes-versioning

Express routes versioning 快速路由版本控制

Module allows individual routes to be versioned separately. 模块允许单独路由单独的版本。 It is agnostic about specific versioning strategies and allows the application to set the version, so you should be able to parse version from headers and set it to req.version in a middleware. 它与特定的版本控制策略无关,并且允许应用程序设置版本,因此您应该能够从标头中解析版本并将其设置为中间件中的req.version。 It supports semver versioning format and symbols to map multiple versions to single function. 它支持semver版本控制格式和符号,以将多个版本映射到单个功能。 Sample code on how it works. 有关其工作方式的示例代码。

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');
}

By default, if the client version doesn't match the version provided in the server, module servers the latest version callback available in that route. 默认情况下,如果客户端版本与服务器中提供的版本不匹配,则模块服务器将在该路由中提供最新的版本回调。 This behavior can be overridden by providing an additional callback. 可以通过提供其他回调来覆盖此行为。 More info and source code available at https://github.com/Prasanna-sr/express-routes-versioning 有关更多信息和源代码,请访问https://github.com/Prasanna-sr/express-routes-versioning

I think you could set a middleware before all your routes to check headers. 我认为您可以在所有路由检查标头之前设置中间件。

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

this is a example , but you could manipulate headers in your router instance and then pass req to other route 这是一个示例,但是您可以在路由器实例中操作标头,然后将req传递给其他路由

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

})

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

There's a small package called totoro-node that helps deal with route management for api versioning. 有一个名为totoro-node的小程序包,可帮助处理api版本控制的路由。 It might help to solve some of the problems you're facing. 这可能有助于解决您面临的一些问题。 You just write a simple api definition like this and you can control which endpoints or api versions to deprecate or inherit into subsequent api versions. 您只需要编写一个简单的api定义,就可以控制要弃用或继承到后续api版本的端点或api版本。 https://www.npmjs.com/package/totoro-node 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
        }
    }
}))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM