你如何处理Node / Express应用程序中的api版本

我对Node.js很新,我正面临以下问题。

我的中间件是以链接api/v1/login和一些端点开始的。 然后api/v1.1引入了另外两个端点。 api/v1.2现在是最后一个,并得到了一些新的端点。

我应该如何高效地处理这个api版本? 你如何使版本中的端点可用于下一个版本?

首先,如果你正在构build一个REST API,并且你刚开始,你可能要考虑使用Restify而不是Express。 尽pipeExpress可以用于此目的,但是Restify已经被devise为具有REST API服务器的所有要求:标准化例外,API版本控制等。

这样说,我相信你的第一个问题是devise上的缺陷。 只有当新的API 与以前的版本向后兼容时,也就是当主要版本增加时(例如从v1到v2),您应该创build单独的端点。 这应该尽可能地发生!
如果您只是添加新function或进行其他调整而不打破现有的代码,那么您不应该创build一个不同的端点。 所以,你不应该为v1.1,v1.2等创build端点,只要v1.0的所有代码也可以在v1.1下工作(如果情况并非如此,不是向后兼容的,因此你应该考虑把版本改为v2)。
请注意,每次引入向后不兼容的更改时,您的所有用户都需要更新其代码,并且您必须在一段时间内支持旧的API,以便让所有用户更新。 对于您(您需要维护旧的代码库)和您的用户(他们需要更新代码),这是一个昂贵的过程,因此应该尽可能less地发生。 另外,对于每个版本,您需要编写文档,创build示例等。
(底线:花费大量的时间来devise你的API服务器,所以它可能会持续下去,尽可能长时间没有后向不兼容的变化)

为了回答你的问题,一个方法可能是为每个API集(每个版本)创build子文件夹,然后相应地设置路由器。 例如,您的项目将如下所示:

 / -- app.js -- routes/ -- -- v1/ -- -- -- auth.js -- -- -- list.js -- -- v2/ -- -- -- auth.js -- -- -- list.js 

这不应该是一个问题:因为v2不是向后兼容v1,所以有可能这两个文件有很大的不同。
然后,在Express上就相应地使用路由器。 例如:

 app.get('/v1/list/:id', v1.list) app.all('/v1/auth', v1.auth) app.get('/v2/list/:id', v2.list) app.all('/v2/auth', v2.auth) 

还有其他的select,但是。 例如,一个更优雅(虽然稍微先进)的解决scheme可以是: http : //j-query.blogspot.ca/2013/01/versioned-apis-with-express.html

注意这个方法

虽然按照每个后向不兼容的变化,API的主要版本应该会有所增加,但是如果您打算在v1和v2之间实现许多重大差异(重用代码的可能性很小),那么这个方法不适合你。

在最后一种情况下,您可能需要为v1和v2创build两个单独的Node.js应用程序,然后使用nginxconfiguration正确的路由。 版本控制不会在应用程序级别完成(每个应用程序都会响应'/ auth','/ list /:id'而不是'/ v1 / auth','/ v1 / list:id'等),但是nginx将前缀“/ v1 /”的请求转发给一个工作服务器,而那些前缀为“/ v2 /”的请求转发给另一个工作服务器。

像restify这样的框架更适合于api版本控制,但是如果你使用express,并且需要一个轻量级的模块来版本化你的路由,那么试试这个npm模块https://www.npmjs.com/package/express-routes-versioning

模块允许单独的路线进行版本控制。 它在服务器上支持基本的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'); } 

我猜你的API违反了REST约束,至less是无状态约束。 检查REST的统一接口约束。 它告诉你如何将客户端与API的实现分开。 之后,你可能不会再需要版本控制了。

如果你不想应用REST约束,那么我认为这个URL只能包含主要的版本号(用来表示不兼容的更改)。 之后,您可以定义供应商特定的MIMEtypes或内容types参数,您可以在其中描述未成年人,如果需要,可以查看并生成版本号。 所以你的客户端应该使用这些版本参数发送accept和content-type标头。

只要提一下,如果你想一次支持多个版本,你必须为每个版本编写文档。