Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/36.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Expressjs中间件静态类型路径和参数冲突路径_Javascript_Node.js_Rest_Express - Fatal编程技术网

Javascript Expressjs中间件静态类型路径和参数冲突路径

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-

我将在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-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
是一个数值。尽管我相信支持多种值类型的更通用的解决方案将是有益的。As
user\u id
可以被替换使用其他标识符,如
用户名
电子邮件
或其他路由路径中的某种标识符。我更新了答案,以包含一个解决方案,该解决方案要求
用户id
为数值。谢谢您的想法。您认为这种方法比使用不同的uri结构来隔离两者更可取吗路径类型?你知道有没有关于这个问题的文档吗?我假设这是在构建更复杂的REST api时遇到的一个非常常见的问题。@Sakki那么你可以说他们可能添加了一个
res.stopRouting()
类似于事件的
stopPropagation
方法。按照当前的实现方式,您可以使用
路由器。使用('/user',requiresAdditionalAuthentication,criticalTasks);路由器。使用('/user',notCiriticalTasks)
如果
criticalTasks
中的任何路由都不匹配,express将停止,您会怎么做?