Routage générique Express-js pour tout couvrir sous et y compris un chemin


96

J'essaie d'avoir une route couvrant tout, /fooy compris /foolui-même. J'ai essayé d'utiliser /foo*quel travail pour tout sauf qu'il ne correspond pas /foo. Observer:

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

Les sorties:

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

Quelles sont mes options? Le mieux que j'ai trouvé est de tracer /fo*ce qui, bien sûr, n'est pas très optimal car cela correspondrait beaucoup trop.


Si vous interceptez toutes les /foo*routes comme ça, ne voulez-vous pas en faire un middleware à la place?
Raynos

3
Faites attention à ce que vous demandez: des /foo*matchs /foo/barmais aussi des matchs /foolishauxquels vous n'aviez probablement pas l'intention.
Wyck

Réponses:


111

Je pense que vous devrez avoir 2 itinéraires. Si vous regardez la ligne 331 du routeur de connexion, le * dans un chemin est remplacé par. + Donc correspondra à 1 ou plusieurs caractères.

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

Si vous avez 2 itinéraires qui effectuent la même action, vous pouvez faire ce qui suit pour le garder SEC .

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 */);pourrait être préférentiel aussi!
Chris Foster

9
Passer un tableau de chaînes est également préférable pour moi. Malheureusement: passer un tableau à app.VERB () est obsolète et sera supprimé dans la version 4.0
CodeWarrior

10
La transmission d'un tableau de chaînes a été restaurée dans Express 4.9.1.
Pete TNT

30

Le routeur de connexion a maintenant été supprimé ( https://github.com/senchalabs/connect/issues/262 ), l'auteur déclarant que vous devez utiliser un framework au-dessus de connect (comme Express) pour le routage.

Express traite actuellement app.get("/foo*") comme app.get(/\/foo(.*)/), supprimant le besoin de deux itinéraires distincts. Ceci est en contraste avec la réponse précédente (faisant référence au routeur de connexion maintenant supprimé) qui déclarait que " *dans un chemin est remplacé par .+".

Mise à jour: Express utilise désormais le module "path-to-regexp" (depuis Express 4.0.0) qui conserve le même comportement dans la version actuellement référencée. Je ne sais pas si la dernière version de ce module conserve le comportement, mais pour l'instant, cette réponse est valable.


Alors devrions-nous utiliser. + Ou *?
Tyler Langan

2
À utiliser /\/foo(.+)/si vous voulez faire correspondre /foosuivi d'un ou plusieurs caractères, et /foo*ou /\/foo(.*)/si vous voulez faire correspondre /foosuivi de zéro ou plusieurs caractères.
Johann

12

Il n'est pas nécessaire d'avoir deux itinéraires.

Ajoutez simplement (/*)?à la fin de votre pathchaîne.

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

Voici un exemple entièrement fonctionnel, n'hésitez pas à copier et coller ceci dans un fichier .js à exécuter avec node, et à jouer avec dans un navigateur (ou 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

Dans le tableau, vous pouvez également utiliser des variables passant à req.params:

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

3

Pour ceux qui apprennent node / express (tout comme moi): n'utilisez pas le routage générique si possible!

Je voulais également implémenter le routage pour GET / users /: id / tout en utilisant le routage générique. Voilà comment je suis arrivé ici.

Heureusement, j'ai aussi trouvé cet article: http://www.jongleberry.com/wildcard-routing-is-an-anti-pattern.html

Bravo, Robert


2
Lien actuellement mort. C'était peut-être la même chose que: jonathanong.github.io/wildcard-routing-is-an-anti-pattern.html
Ron Burk

@RonBurk votre URL semble également être morte. Comment puis-je avoir un caractère générique facultatif après un paramètre nommé? "/ quelque chose /: id (/ *)?" ne fonctionne pas ..
Soichi Hayashi


existe-t-il une alternative au routage générique si je n'ai aucune idée de ce qui vient après la partie initiale de l'URL?
Michael

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.