Express-js wildcard routing to cover everything under and including a path

I'm trying to have one route cover everything under /foo including /foo itself. I've tried using /foo* which work for everything except it doesn't match /foo. Observe:

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);

Outputs:

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

What are my options? The best I've come up with is to route /fo* which of course isn't very optimal as it would match way too much.

140374 次浏览

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

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

如果你有两个路由执行相同的动作,你可以做到以下保持它 干的

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);

连接路由器现在已经被删除(https://github.com/senchalabs/connect/issues/262) ,作者指出您应该使用连接之上的框架(如 Express)进行路由。

目前治疗 app.get("/foo*")表示为 app.get(/\/foo(.*)/),这样就不需要两条独立的路线。这与之前的答案(指现在已经移除的连接路由器)相反,后者说“路径中的 *.+替换”。

Update: Express now uses the "path-to-regexp" module (since Express 4.0.0) which maintains the same behavior in the version currently referenced. It's unclear to me whether the latest version of that module keeps the behavior, but for now this answer stands.

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

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

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

我还想使用通配符路由实现 GET/users/: id/whatever 的路由。

更多信息: https://blog.praveen.science/wildcard-routing-is-an-anti-pattern/

没有必要有两条路线。

Simply add (/*)? at the end of your path string.

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

下面是一个完整的示例,您可以将其复制并粘贴到。Js 文件与节点一起运行,并在浏览器中使用它(或 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!'))