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.


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

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.


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!'))

9

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

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

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


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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.