Enrutamiento comodín Express-js para cubrir todo lo que se encuentra debajo de una ruta incluida

96

Estoy tratando de tener una ruta que cubra todo, /fooincluido él /foomismo. He intentado usar /foo*which work para todo, excepto que no coincide /foo. Observar:

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

Salidas:

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

¿Cuáles son mis opciones? Lo mejor que se me ha ocurrido es una ruta /fo*que, por supuesto, no es muy óptima, ya que coincidiría demasiado.

Kit Sunde
fuente
Si intercepta todas las /foo*rutas así, ¿no quiere convertirlo en middleware?
Raynos
3
Tenga cuidado con lo que pide: /foo*coincidencias /foo/barpero también coincidencias /foolishque probablemente no pretendía.
Wyck

Respuestas:

111

Creo que tendrás que tener 2 rutas. Si observa la línea 331 del enrutador de conexión, el * en una ruta se reemplaza con. +, Por lo que coincidirá con 1 o más caracteres.

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

Si tiene 2 rutas que realizan la misma acción, puede hacer lo siguiente para mantenerla SECA .

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
fuente
101
app.get(["/foo", "/foo*"], /* function */);¡También podría ser preferencial!
Chris Foster
9
Pasar una serie de cadenas también es preferencial para mí. Desafortunadamente: pasar una matriz a app.VERB () está obsoleto y se eliminará en 4.0
CodeWarrior
10
El paso de una matriz de cadenas se ha restaurado en Express 4.9.1.
Pete TNT
30

El enrutador de conexión ahora se ha eliminado ( https://github.com/senchalabs/connect/issues/262 ), el autor afirma que debe usar un marco en la parte superior de la conexión (como Express) para el enrutamiento.

Express actualmente trata app.get("/foo*") como app.get(/\/foo(.*)/), eliminando la necesidad de dos rutas separadas. Esto contrasta con la respuesta anterior (refiriéndose al enrutador de conexión ahora eliminado) que decía que " *en una ruta se reemplaza con .+".

Actualización: Express ahora usa el módulo "path-to-regexp" (desde Express 4.0.0) que mantiene el mismo comportamiento en la versión actualmente referenciada. No me queda claro si la última versión de ese módulo mantiene el comportamiento, pero por ahora esta respuesta se mantiene.

Johann
fuente
Entonces, ¿deberíamos usar. + O *?
Tyler Langan
2
Úselo /\/foo(.+)/si desea hacer coincidir /fooseguido de uno o más caracteres, /foo*o /\/foo(.*)/si desea hacer coincidir /fooseguido de cero o más caracteres.
Johann
12

No es necesario tener dos rutas.

Simplemente agregue (/*)?al final de su pathcadena.

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

Aquí hay un ejemplo completamente funcional, siéntase libre de copiar y pegar esto en un archivo .js para ejecutarlo con el nodo y jugar con él en un navegador (o 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!'))
Somo S.
fuente
9

En la matriz también puede usar variables que pasan a req.params:

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

Para aquellos que están aprendiendo node / express (como yo): ¡no use el enrutamiento comodín si es posible!

También quería implementar el enrutamiento para GET / users /: id / anything usando el enrutamiento comodín. Así es como llegué aquí.

Afortunadamente también he encontrado este artículo: http://www.jongleberry.com/wildcard-routing-is-an-anti-pattern.html

Saludos, Robert

Throbi
fuente
2
Link actualmente muerto. Quizás era lo mismo que: jonathanong.github.io/wildcard-routing-is-an-anti-pattern.html
Ron Burk
@RonBurk, su URL también parece estar muerta. ¿Cómo puedo tener un comodín opcional después de un parámetro con nombre? "/ algo /: id (/ *)?" no funciona ..
Soichi Hayashi
Probablemente todavía estará en la caché de Google por un tiempo: webcache.googleusercontent.com/…
Ron Burk
¿Existe una alternativa al enrutamiento comodín si no tengo idea de lo que viene después de la parte inicial de la URL?
Michael
1
Aquí está el republicado: El enrutamiento comodín es un antipatrón
Praveen Kumar Purushothaman