Express-js Wildcard-Routing, um alles unter und einschließlich eines Pfads abzudecken

96

Ich versuche , einen Weg Abdeckung alles haben unter /fooeinschließlich /fooselbst. Ich habe versucht, /foo*welche Arbeit für alles zu verwenden, außer dass sie nicht übereinstimmt /foo. Beobachten:

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

Ausgänge:

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

Was sind meine Optionen? Das Beste, was ich mir ausgedacht habe, ist eine Route, /fo*die natürlich nicht sehr optimal ist, da sie viel zu sehr zusammenpassen würde.

Kit Sunde
quelle
Wenn Sie alle /foo*Routen so abfangen , möchten Sie sie nicht stattdessen zur Middleware machen?
Raynos
3
Seien Sie vorsichtig, wonach Sie fragen: /foo*Streichhölzer, /foo/baraber auch Streichhölzer, /foolishdie Sie wahrscheinlich nicht beabsichtigt haben.
Wyck

Antworten:

111

Ich denke, Sie müssen 2 Routen haben. Wenn Sie sich Zeile 331 des Verbindungsrouters ansehen, wird das * in einem Pfad durch. + Ersetzt, sodass 1 oder mehr Zeichen übereinstimmen.

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

Wenn Sie zwei Routen haben, die dieselbe Aktion ausführen, können Sie Folgendes tun, um sie trocken zu halten .

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);
serby
quelle
101
app.get(["/foo", "/foo*"], /* function */);könnte auch bevorzugt sein!
Chris Foster
9
Das Übergeben einer Reihe von Zeichenfolgen ist mir ebenfalls vorzuziehen. Leider: Das Übergeben eines Arrays an app.VERB () ist veraltet und wird in 4.0
CodeWarrior
10
Die Übergabe eines Arrays von Zeichenfolgen wurde in Express 4.9.1 wiederhergestellt.
Pete TNT
30

Der Verbindungsrouter wurde jetzt entfernt ( https://github.com/senchalabs/connect/issues/262 ). Der Autor gab an, dass Sie für das Routing ein Framework über Connect (wie Express) verwenden sollten.

Express wird derzeit app.get("/foo*") als behandeltapp.get(/\/foo(.*)/) , sodass keine zwei separaten Routen erforderlich sind. Dies steht im Gegensatz zu der vorherigen Antwort (bezogen auf den jetzt entfernten Verbindungsrouter), in der angegeben wurde, dass " *in einem Pfad durch .+" ersetzt wird.

Update: Express verwendet jetzt das Modul "Pfad zum regulären Ausdruck" (seit Express 4.0.0), das das gleiche Verhalten in der aktuell referenzierten Version beibehält . Es ist mir unklar, ob die neueste Version dieses Moduls das Verhalten beibehält, aber für den Moment steht diese Antwort.

Johann
quelle
Also sollten wir. + Oder * verwenden?
Tyler Langan
2
Verwenden /\/foo(.+)/Sie diese Option, wenn Sie übereinstimmen möchten, /foogefolgt von einem oder mehreren Zeichen, /foo*oder /\/foo(.*)/wenn Sie übereinstimmen möchten, /foogefolgt von null oder mehreren Zeichen.
Johann
12

Es ist nicht erforderlich, zwei Routen zu haben.

Fügen Sie einfach (/*)?am Ende Ihrer pathZeichenfolge hinzu.

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

Hier ist ein voll funktionsfähiges Beispiel. Sie können es kopieren und in eine .js-Datei einfügen, um es mit dem Knoten auszuführen, und damit in einem Browser (oder Curl) spielen:

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!'))
Somo S.
quelle
9

Im Array können Sie auch Variablen verwenden, die an req.params übergeben werden:

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

Für diejenigen, die Node / Express lernen (genau wie ich): Verwenden Sie nach Möglichkeit kein Wildcard-Routing!

Ich wollte auch das Routing für GET / users /: id / Whatever mithilfe von Wildcard-Routing implementieren. So bin ich hierher gekommen.

Zum Glück habe ich auch diesen Artikel gefunden: http://www.jongleberry.com/wildcard-routing-is-an-anti-pattern.html

Prost, Robert

throbi
quelle
2
Link derzeit tot. Vielleicht war es dasselbe wie: jonathanong.github.io/wildcard-routing-is-an-anti-pattern.html
Ron Burk
@ RonBurk Ihre URL scheint auch tot zu sein. Wie kann ich einen optionalen Platzhalter nach einem benannten Parameter haben? "/ etwas /: id (/ *)?" funktioniert nicht ..
Soichi Hayashi
Wahrscheinlich wird es noch eine Weile im Google-Cache sein: webcache.googleusercontent.com/…
Ron Burk
Gibt es eine Alternative zum Platzhalter-Routing, wenn ich keine Ahnung habe, was nach dem ersten Teil der URL kommt?
Michael
1
Hier ist die neu veröffentlichte: Wildcard Routing ist ein Anti-Pattern
Praveen Kumar Purushothaman