パスの下およびパスを含むすべてをカバーするExpress-jsワイルドカードルーティング


96

自分自身/fooを含めてすべてをカバーする1つのルートを作成しようとしてい/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*ようなすべてのルートをインターセプトする場合は、代わりにミドルウェアにしたくないですか?
レイノス

3
あなたが求めるものに注意してください: /foo*マッチ/foo/barだけでなく、/foolishおそらく意図していないマッチも。
Wyck

回答:


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で復元されました。
ピートTNT

30

接続ルーターは削除され(https://github.com/senchalabs/connect/issues/262)、著者はルーティングには接続(Expressなど)の上にフレームワークを使用する必要があると述べています。

Expressは現在 app.get("/foo*")として扱いapp.get(/\/foo(.*)/)、2つの別々のルートの必要性を排除しています。これは、「*パス内の"が" に置き換えられる」と述べた以前の回答(現在削除されている接続ルーターを参照)とは対照的.+です。

更新: Expressは、現在参照されているバージョンで同じ動作を維持する「regexpへのパス」モジュール(Express 4.0.0以降)を使用するようになりました。そのモジュールの最新バージョンが動作を維持するかどうかは不明ですが、現時点ではこの答えは有効です。


。+または*を使用する必要がありますか?
タイラーランガン、2015

2
使用/\/foo(.+)/あなたが一致する場合、/foo一の以上の文字が続き、/foo*または/\/foo(.*)/あなたが一致させたい場合は/foo、ゼロ以上の文字が続きます。
ヨハン

12

2つのルートを持つ必要はありません。

文字列(/*)?の最後に追加するだけpathです。

例えば、 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!'))

9

配列では、req.paramsに渡す変数を使用することもできます。

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

3

(ちょうど私のように)node / expressを学んでいる人のために:可能であればワイルドカードルーティングを使わないでください!

また、ワイルドカードルーティングを使用して、GET / users /:id / whateverのルーティングを実装したいと思っていました。これは私がここに着いた方法です。

幸いにも私はこの記事を見つけました:http : //www.jongleberry.com/wildcard-routing-is-an-anti-pattern.html

乾杯、ロバート


2
リンクは現在死んでいます。おそらくそれは同じでした:jonathanong.github.io/wildcard-routing-is-an-anti-pattern.html
Ron Burk

@RonBurkあなたのURLも無効になっているようです。名前付きパラメータの後にオプションのワイルドカードを付けるにはどうすればよいですか?「/ something /:id(/ *)?」動作しません..
林宗一

おそらく、まだしばらくの間、Googleのキャッシュになります。webcache.googleusercontent.com/...
ロン・バーク

URLの最初の部分の後に何が来るかわからない場合、ワイルドカードルーティングの代替手段はありますか?
マイケル

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.