Javascript 是否可以在express中重新分配req.params?

Javascript 是否可以在express中重新分配req.params?,javascript,node.js,express,Javascript,Node.js,Express,我将从一些上下文开始: 我有一个RESTful API服务器,其中包括用于管理用户的路由;e、 g PUT…/users/:id/profile 作为身份验证流程的一部分,我们验证用户的身份,并将url中的id与从IDP检索到的id进行比较 我想做的是实施“自我”替代方法;其中,用户不需要在url中提供其id,只需提供“我”即可,并根据其身份验证使用从IDP检索的id重新分配该id。我见过谷歌在他们的一些API中这样做。例如。 ../users/me/profile 到目前为止,我一直在尝试一个

我将从一些上下文开始: 我有一个RESTful API服务器,其中包括用于管理用户的路由;e、 g

PUT…/users/:id/profile

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

我想做的是实施“自我”替代方法;其中,用户不需要在url中提供其id,只需提供“我”即可,并根据其身份验证使用从IDP检索的id重新分配该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不会像我所希望的那样在整个应用程序中传播

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

我知道req.params是通过解析url构建的;那么修改url是一种选择吗?;将“我”替换为id;那么req.params是否按预期填充?如果是这样,如何实现这一目标

或者,如果你有一个更好的替代方案来让上述“我”的替代行为发挥作用,那么我洗耳恭听

全局中间件(使用
app.use()
router.use()
添加的)通常甚至不知道任何声明参数的路由处理程序,因此
req.params
通常都不会填充

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

app.put('/users/:id/profile', middleware, ...)
但这需要重写所有的路由处理程序

正如您已经正确指出的,您可以修改URL:

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
标识符)的所有URL的列表,而不必专门匹配每个URL

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

这应该添加到声明参数的路由器中,或者直接在路由处理程序中,或者在装入点中

一个复杂的例子:

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
,所以它应该获得解析功能。

…如果URL中没有提供用户id,那么应该在其他地方提供。否则,RESTful应用程序如何知道用户id?是的,我们可以从身份验证流中检索id;但是问题是我的逻辑检查了req.params.id的id。我试图做的是将我从身份验证流收到的id注入req.params.id。明白了。。。然后您尝试分配
req.params.id
应该可以工作。刚刚测试过,一切看起来都很好,即您可以分配
req.params.id
任何您想要的。您是否尝试为/users/me/profile创建新路由?在本地再次测试;修改后的req.params.id在当前中间件功能期间保持不变。调用链中的下一个中间件函数后,将重置req.params。然后需要使用next()将其从链中的一个函数传递到另一个函数。。。类似这样的东西
router.get('/',函数(req,res,next){next(null,{some:data});},foo);函数foo(req,res,next,data){}
对不起,应该已经澄清了更多;是的,我使用的是你提到的路由处理程序。然而,我有路由器路由到路由器。我有一个用于/users/:id的路由器,它将路由器路由到另一个查找/profile等的路由器。因此,此时的req.url仅显示/profile。我试图修改originalUrl,但似乎不起作用…@Mitch请看我的编辑,有一种重写的替代方法可能更健壮。今天做了一些测试,req.param()方法非常有效。非常感谢你!我不太清楚为什么在req.param()中设置req.params.id有效,但在其他中间件中无效。@Mitch我认为在处理路由的
req.param
过程中调用
req.param()
,而在请求到达路由处理程序之前调用常规中间件。
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);