Javascript 是否可以在express中重新分配req.params?
我将从一些上下文开始: 我有一个RESTful API服务器,其中包括用于管理用户的路由;e、 gJavascript 是否可以在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 到目前为止,我一直在尝试一个
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);