Express.js路由:可选的splat参数?


80

我有一条看起来像这样的路线:

app.all('/path/:namedParam/*splat?',function(req,res,next){
  if(!req.params.length){
    // do something when there is no splat
  } else {
    // do something with splat
  }
});

但是,这行不通-如果我打电话,path/foo/bar它会到达路线,但是如果我打电话path/foo,它就不会。

是否可以有一个可选的splat参数,或者我必须使用正则表达式来检测到这一点?

编辑

更清楚地说,这是我要达到的要求:

  • 第一和第二个参数是必需的
  • 第一个参数是静态的,第二个参数是命名的参数。
  • 可以附加任意数量的可选附加参数,并且仍然可以实现。

1
你想做什么?如果您不需要了解splat,那就去做吧'/path/:firstParam/*'。如果需要,请执行'/path/:firstParam/:secondParam?/*'
乔纳森·翁

1
我希望splat是可选的-您提供的第一个示例将不匹配/path/foo,(这就是我想要可选splat之前我的路线的样子)。另外,在您的第二个示例中,添加splat实际上会否定可选的第二个参数-/path/foo不会匹配您的第二个模式(/path/foo/bar在这方面也不会匹配...)-Express路由器中比较烦人的部分之一。
杰西2012年

1
就个人而言,我只想/path/:firstParam/path/:firstParam/:secondParam/两个单独的路由器共享一个控制器。无需混淆您的网址
Jonathan Ong 2012年

n对于应用程序的设计,必须具有端点-我不仅要路由到1-3个参数,它可以是任意数量,因此不能限制参数的数量(当然,我可以创建10个端点,但表达出来的意思并没有比在路线上做到更好。我可以使用正则表达式路由来解决我的问题(我现在正在做的事情),但是我希望有一个可读的选项。
杰西2012年

令人惊讶的是,开发人员没有想到仅对命名的可选参数使用括号。即/path/:param(/:otherOptionalParam)
r3wt

Answers:


110

这适用于Express 4上的/ path和/ path / foo,请注意*before ?

router.get('/path/:id*?', function(req, res, next) {
    res.render('page', { title: req.params.id });
});

42
请注意,尽管这样做确实可行,但是如果您访问/path/foo/bar/bazzlereq.params.id将等于foo,并且req.params[0]将等于/bar/bazzle,这可能会使某些人绊倒。较干净的解决方案是将路径定义为/path/*?,在express 4中将其设置req.params[0]foo/bar/bazzle,这可能更接近您要查找的内容。
2015年

最好使用url编码您的可选参数-允许任何带有斜杠的内容意味着如果您想添加类似app.get('path /:required1 /:required2 /:optional?*'的路径,则会遇到冲突。 ,经理)
约旦

@Jesse有什么方法可以制成最后一部分吗?例如,我想匹配/path/foo/bar 匹配/path/foo。我试过,'/path/:id/**似乎也匹配空字符串。
富兰克林·于

72

我只是遇到了同样的问题并解决了。这是我使用的:

app.get('path/:required/:optional?*', ...)

这应该工作path/meowpath/meow/voofpath/meow/voof/moo/etc...

通过删除和/之间?,似乎*最后一个也/变为可选,而:optional?保持可选。


凉!我刚刚对此进行了测试(在Express 3.0.0中,尚未在2.x中进行测试),并且它可以工作。这绝对比我的RegEx骇客干净。
Jesse

5
您知道在哪里可以阅读有关这些预定义关键字的更多信息?
亚诺什

8
在express 4.0x中,此功能似乎不再起作用
悔悟过失2015年

2
@chris为快递4回答了此问题-由于这是最新的,因此我将接受的答案移至他的位置。
杰西

使用此方法会遇到奇怪的错误,对于其中包含零的数字,express会将其删除。例如/:id,其中id = 904,req.params.id = 9和req.params.0 = 04(出于某种原因,express在此转储其余部分)。克里斯(Chris)的答案解决了这一问题
emiidee'Aug

17

这会做你所追求的吗?

app.all('/path/:namedParam/:optionalParam?',function(req,res,next){
  if(!req.params.optionalParam){
    // do something when there is no optionalParam
  } else {
    // do something with optionalParam
  }
});

如果您还没有看过,请点击此处了解有关Express路由的更多信息:http : //expressjs.com/guide/routing.html


2
该解决方案将匹配/path/foo/bar,但不/path/foo/bar/baz-的*图示的比赛.+,这是必要的我在做什么-我肯定RTFM,似乎并没有提到它,所以也许这是不可能的...
杰西

3

这是我解决此问题的当前方法,似乎express并没有通过可选的名为param支持任何数量的splat参数:

app.all(/\/path\/([^\/]+)\/?(.+)?/,function(req,res,next){
  // Note: this is all hacked together because express does not appear to support optional splats.
  var params = req.params[1] ? [req.params[1]] : [],
      name = req.params[0];
  if(!params.length){
    // do something when there is no splat
  } else {
    // do something with splat
  }
});

我很乐意将此命名为params的用法用于可读性和一致性-如果出现另一个答案允许我接受它。


2

假设您有以下网址: /api/readFile/c:/a/a.txt

如果您想req.params.path成为c:

'/api/readFile/:path*

如果您想req.params.path成为c:/a/a.txt

'/api/readFile/:path([^/]*)'

0

上述使用可选解决方案的解决方案在Express 4中不起作用。我尝试了几种使用搜索模式的方法,但均不起作用。然后我发现了这种方法,并且似乎为无限的嵌套路径而被解雇,http://expressjs.com/api.html#router

// this will only be invoked if the path starts with /bar from the mount point
router.use('/bar', function(req, res, next) {
  // ... maybe some additional /bar logging ...

  // to get the url after bar, you can try
  var filepath = req.originalUrl.replace(req.baseUrl, "");

  next();
});

它与所有/ bar,/ bar / z,/ bar / a / b / c等匹配。此后,您可以阅读req.originalUrl,因为未填充参数,例如。您可以尝试比较baseUrl和originalUrl以获取剩余路径。


0

我通过使用中间件的组合解决了这个问题,该中间件在url和末尾添加了反斜杠router.get('/bar/*?', ...,它将在之后拾取所有内容/bar/undefined如果是则返回/bar/。如果访问者要求/barexpress-slash中间件将在请求中添加一个斜线并将请求转换为/bar/

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.