可以在快递中重新分配req.params吗?

时间:2017-08-28 10:43:10

标签: javascript node.js express

我将从一些背景开始: 我有一个RESTful API服务器,包括管理用户的路由; e.g。

PUT .../users/:id/profile

作为验证流程的一部分,我们会验证用户的身份,并将网址中的ID与从IDP中检索到的ID进行比较。

我想要做的就是实施一个“我'替代方法;用户,而不是在网址中提供他们的ID,可以简单地提供“我”。相反,id将根据其身份验证从IDP检索到的id重新分配。我已经看到谷歌为他们的一些API做了这个。例如。 .../users/me/profile

到目前为止,我一直试图进行简单的替换,并假设修改后的req.params会向前传播:

req.params.id = req.params.id === 'me'
  ? session.id
  : req.params.id

这不起作用,所以我做了一些阅读,显然req.params是用每个中间件函数构建的(当调用.use()时),所以重新分配req.params.id不会&# 39;按照我的希望在整个应用程序中传播。

目前我们所有的业务逻辑都从req.params中提取了id,所以我想知道是否有办法让上述行为起作用以避免重构我的所有业务逻辑?

我知道req.params是通过解析url构建的;那么修改网址是一种选择吗?替换“我”#39;与身份;以便req.params按预期填充?如果是这样,怎么能实现呢?

或者,如果你有更好的选择来获得上述' me'工作的替代行为然后我全都耳朵!

1 个答案:

答案 0 :(得分:1)

全局中间件(您使用app.use()router.use()添加)通常甚至不知道任何声明参数的路由处理程序,因此req.params通常不是{\ n}甚至人口稠密。

解决方案是"内联"修改中间件:

app.put('/users/:id/profile', middleware, ...)

但这需要重写所有路由处理程序。

正如您已经正确指出的那样,可以修改网址:

app.use(function(req, res, next) {
  if (req.url === '/users/me/profile') {
    req.url = '/users/1234/profile';
  }
  next();
});

app.put('/users/:id/profile', ...)

您可以执行子字符串匹配,也可以使用可能包含:id参数的所有网址列表,而不必专门匹配每个网址(因此,可能包含me标识符。

我刚刚意识到这应该有效(使用req.param()):

router.param('id', function(req, res, next, id) {
  if (id === 'me') {
    req.params.id = '1234';
  }
  next();
});

这应该添加到声明参数的路由器中,无论是直接路由处理程序还是挂载点。

一个错综复杂的例子:

let childRouter = express.Router({ mergeParams : true });

childRouter.put('/profile', ...);

let parentRouter = express.Router({ mergeParams : true });

parentRouter.use('/:id', childRouter);

parentRouter.param('id', function(req, res, next, id) {
  if (id === 'me') {
    req.params.id = '1234';
  }
  next();
});

app.use('/users', parentRouter);

因为parentRouter声明了一个挂载点/:id,它应该得到解析函数。