Javascript Expressjs中间件静态类型路径和参数冲突路径
我将在expressjs中为经过身份验证的用户和未经身份验证的用户实现REST端点。我目前对REST的理解导致我采用以下设计模式: 用户资源 令牌用户:Javascript Expressjs中间件静态类型路径和参数冲突路径,javascript,node.js,rest,express,Javascript,Node.js,Rest,Express,我将在expressjs中为经过身份验证的用户和未经身份验证的用户实现REST端点。我目前对REST的理解导致我采用以下设计模式: 用户资源 令牌用户: /users/self GET, PATCH /users POST /users/:user_id GET /users/self/profile-images POST /users/self/profile-images/:profile_image_id PUT, DELETE /users/:user_id/profile-
/users/self GET, PATCH
/users POST
/users/:user_id GET
/users/self/profile-images POST
/users/self/profile-images/:profile_image_id PUT, DELETE
/users/:user_id/profile-images GET
非令牌用户:
/users/self GET, PATCH
/users POST
/users/:user_id GET
/users/self/profile-images POST
/users/self/profile-images/:profile_image_id PUT, DELETE
/users/:user_id/profile-images GET
配置文件图像资源
令牌用户:
/users/self GET, PATCH
/users POST
/users/:user_id GET
/users/self/profile-images POST
/users/self/profile-images/:profile_image_id PUT, DELETE
/users/:user_id/profile-images GET
非令牌用户:
/users/self GET, PATCH
/users POST
/users/:user_id GET
/users/self/profile-images POST
/users/self/profile-images/:profile_image_id PUT, DELETE
/users/:user_id/profile-images GET
我正在努力找出如何在没有:user\u id
参数变成self
的情况下使用此模式,即{user\u id:'self'}
。我希望它们可以作为两种独立的路径类型,没有干扰,一种是严格的,另一种是动态的。这可能吗?如果是,怎么做
我当前实现的代码示例如下所示:
// instPrivateUserRestRoutes.js (token-user)
router.use('/users/self', [
instAccountRestRoutes(restControllers),
instAuthenticationSessionRestRoutes(restControllers),
instPrivateProfileImageRestRoutes(restControllers)
])
// instPublicUserRestRoutes.js (non-token user)
router.use('/users/:user_id', [
instPublicProfileImageRestRoutes(restControllers)
])
// instRestApp.js (mount point for top resources)
router.use(instPrivateUserRestRoutes(restControllers))
router.use(instPublicUserRestRoutes(restControllers))
您可以做些什么来创建一个条件路由中间件。factory dunction将决定应该使用哪个路由器的回调方法作为第一个参数,将路由器列表作为第二个参数,并返回一个新的中间战,该中间战有条件地使用其中一个路由
function conditionalRouting(cond, routes) {
return function (req, res, next) {
try{
// get the index for the router that should be used
var idx = cond(req, res)
// call this router and pass req, res and next to it
routes[idx](req, res, next)
} catch(err) {
// in the case an error occurs in on of the steps "throw" that error
next(err)
}
}
}
然后您可以这样使用它:
app.use(
'/users/:user_id',
conditionalRouting(
(req, _) => req.params.user_id === 'self' ? 0:1,
[routerForSelf, routerForUser]
))
另一种方法是使用触发not found错误的中间件显式处理此情况:
function forceNotFound(req, res, next) {
var error = new Error('resource not found')
error.status = 404
next(error)
}
并将其添加为最后一个中间件
router.use('/users/self', [
instAccountRestRoutes(restControllers),
instAuthenticationSessionRestRoutes(restControllers),
instPrivateProfileImageRestRoutes(restControllers),
forceNotFound
])
这样一来,express显然应该在该点停止
这看起来与标准的无法获取/path
不同,但您通常不希望显示这些默认错误消息
如果你想得到同样的信息,你可以写:
var parseUrl = require('parseurl')
var encodeUrl = require('encodeurl')
app.use((req, res, next) => {
var msg = 'Cannot ' + req.method + ' ' + encodeUrl(parseUrl.original(req).pathname)
var error = new Error(msg)
error.status = 404
next(error)
})
如果您只想处理数字ID,可以使用:
router.use('/users/:user_id(\\d+)', [
instPublicProfileImageRestRoutes(restControllers)
])
这样,只有当
用户id
是数字的时候才会调用InsPublicProfileImageRestroutes
。问题出在哪里并不清楚。如果router.use中的其中一个路由是if,则不应调用在router.use中注册的路由('/users/:user_id'
)(“/users/self”,
处理请求。因此,在这种情况下,如果uri以/users/self
?@t.niese/users/:当我向/users/self/profile images GET
发出请求时,调用的是InstPublicProfileImageResroutes
,这不是在e目标路由。因此,我期望得到404 Not Found响应。我的目的是将这两种路径类型彼此隔离。我的担忧源于这样一个事实,即情况似乎并非如此。我可能错过了代码中的某些内容,或者我误解了expressjs中间件的组成。它是用户id
数字还是数字除了self
之外的任何东西,因为如果user\u id
只能是一个数值,那么就会有另一个解决方案?@t.niese在这种情况下user\u id
是一个数值。尽管我相信支持多种值类型的更通用的解决方案将是有益的。Asuser\u id
可以被替换使用其他标识符,如用户名
或电子邮件
或其他路由路径中的某种标识符。我更新了答案,以包含一个解决方案,该解决方案要求用户id
为数值。谢谢您的想法。您认为这种方法比使用不同的uri结构来隔离两者更可取吗路径类型?你知道有没有关于这个问题的文档吗?我假设这是在构建更复杂的REST api时遇到的一个非常常见的问题。@Sakki那么你可以说他们可能添加了一个res.stopRouting()
类似于事件的stopPropagation
方法。按照当前的实现方式,您可以使用路由器。使用('/user',requiresAdditionalAuthentication,criticalTasks);路由器。使用('/user',notCiriticalTasks)
如果criticalTasks
中的任何路由都不匹配,express将停止,您会怎么做?