我将从一些背景开始: 我有一个 RESTful API 服务器,其中包含用于管理用户的路由;例如
PUT .../users/:id/profile
作为身份验证流程的一部分,我们验证用户的身份并将网址中的 ID 与从 IDP 检索到的 ID 进行比较。
我想做的是实现“我”的替代方法;用户可以简单地提供“me”,而不是在 url 中提供其 id,并且根据其身份验证,使用从 IDP 检索到的 id 重新分配 id。我见过 Google 对他们的一些 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 是一种选择吗?将“me”替换为 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', ...)
您不必专门匹配每个 URL,而是可以执行子字符串匹配,或使用可能包含 :id
参数的所有 URL 的列表(因此,可能包含 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
,所以它应该获得解析函数。
关于javascript - 是否可以在express中重新分配req.params?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45917143/