Express-js通配符路由覆盖了路径下的所有内容,包括路径


96

我试图让一条路线涵盖/foo包括/foo自身在内的所有事物。我试过将/foo*所有东西都用哪一项工作,除非它不匹配/foo。观察:

var express = require("express"),
    app = express.createServer();

app.get("/foo*", function(req, res, next){
  res.write("Foo*\n");
  next();
});

app.get("/foo", function(req, res){
  res.end("Foo\n");
});

app.get("/foo/bar", function(req, res){
  res.end("Foo Bar\n");
});

app.listen(3000);

输出:

$ curl localhost:3000/foo
Foo
$ curl localhost:3000/foo/bar
Foo*
Foo Bar

我有什么选择?我想出的最好的方法是路由/fo*哪个当然不是最佳选择,因为它匹配得太多了。


如果您要拦截所有这样的/foo*路由,您是否要使其成为中间件?
雷诺斯2011年

3
请谨慎要求: /foo*匹配,/foo/bar但还要匹配/foolish您可能不想要的匹配。
Wyck

Answers:


111

我认为您将必须有2条路线。如果查看连接路由器的第331行,则路径中的*将替换为。+,因此将匹配1个或多个字符。

https://github.com/senchalabs/connect/blob/master/lib/middleware/router.js

如果您有2条路由执行相同的操作,则可以执行以下操作以使其保持DRY状态

var express = require("express"),
    app = express.createServer();

function fooRoute(req, res, next) {
  res.end("Foo Route\n");
}

app.get("/foo*", fooRoute);
app.get("/foo", fooRoute);

app.listen(3000);

101
app.get(["/foo", "/foo*"], /* function */);可能也很优惠!
克里斯·福斯特

9
对我来说,传递一个字符串数组也是优先选择的。不幸的是:不赞成将数组传递给app.VERB()并将在4.0中删除
CodeWarrior

10
Express 4.9.1中已还原了传递字符串数组的操作。
Pete TNT

30

现在已删除了连接路由器(https://github.com/senchalabs/connect/issues/262),作者指出,应在连接顶部使用框架(如Express)进行路由。

表示目前治疗 app.get("/foo*")作为app.get(/\/foo(.*)/),消除了对两个单独的路由需求。这与先前的回答(指现在已删除的连接路由器)相反,前一个回答指出“ *路径中的替换为.+”。

更新: Express现在使用“ path-to-regexp”模块(自Express 4.0.0起),该模块在当前引用的版本中保持相同的行为。我尚不清楚该模块的最新版本是否保留了该行为,但就目前而言,这个答案仍然成立。


那么我们应该使用。+还是*?
泰勒·兰根

2
使用/\/foo(.+)/,如果你想匹配/foo后跟一个或多个字符,且/foo*/\/foo(.*)/如果你想匹配/foo后跟零个或多个字符。
2015年

12

不必有两条路线。

只需(/*)?path字符串末尾添加即可。

例如, app.get('/hello/world(/*)?' /* ... */)

这是一个完整的示例,可以将其复制并粘贴到.js文件中以与node一起运行,并在浏览器(或curl)中进行播放:

const app = require('express')()

// will be able to match all of the following
const test1 = 'http://localhost:3000/hello/world'
const test2 = 'http://localhost:3000/hello/world/'
const test3 = 'http://localhost:3000/hello/world/with/more/stuff'

// but fail at this one
const failTest = 'http://localhost:3000/foo/world'

app.get('/hello/world(/*)?', (req, res) => res.send(`
    This will match at example endpoints: <br><br>
    <pre><a href="${test1}">${test1}</a></pre>
    <pre><a href="${test2}">${test2}</a></pre>
    <pre><a href="${test3}">${test3}</a></pre>

    <br><br> Will NOT match at: <pre><a href="${failTest}">${failTest}</a></pre>
`))

app.listen(3000, () => console.log('Check this out in a browser at http://localhost:3000/hello/world!'))

9

在数组中,您还可以使用传递给req.params的变量:

app.get(["/:foo", "/:foo/:bar"], /* function */);

3

对于那些正在学习节点/表达的人(就像我一样):如果可能,不要使用通配符路由!

我还想使用通配符路由来实现GET / users /:id /的路由。这就是我到达这里的方式。

幸运的是,我还发现了这篇文章:http : //www.jongleberry.com/wildcard-routing-is-an-anti-pattern.html

干杯,罗伯特


2
链接当前无效。也许与以下内容相同:jonathanong.github.io/wildcard-routing-is-an-anti-pattern.html
罗恩·伯克

@RonBurk您的URL似乎也已死。.如何命名参数使用可选的通配符?“ / something /:id(/ *)?” 行不通..
林智一(Soichi Hayashi)

可能仍会在Google缓存中保留一段时间:webcache.googleusercontent.com/…–
罗恩·伯克

如果我不知道URL的初始部分之后会出现什么,是否可以使用通配符路由?
迈克尔(Michael)

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.