Roteamento de curinga Express-js para cobrir tudo sob e incluindo um caminho

96

Estou tentando fazer com que uma rota cubra tudo /fooincluindo a /foosi mesma. Eu tentei usar /foo*esse trabalho para tudo, exceto que não corresponde /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);

Saídas:

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

Quais são minhas opções? O melhor que descobri é a rota, o /fo*que obviamente não é muito ideal, pois combinaria demais.

Kit Sunde
fonte
Se você está interceptando todas as /foo*rotas assim, não quer torná-lo um middleware?
Raynos
3
Tenha cuidado com o que você pede: /foo*correspondências, /foo/barmas também correspondências /foolishque você provavelmente não pretendia.
Wyck

Respostas:

111

Eu acho que você terá que ter 2 rotas. Se você olhar a linha 331 do roteador de conexão, o * em um caminho é substituído por. +, Portanto, corresponderá a 1 ou mais caracteres.

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

Se você tiver 2 rotas que executam a mesma ação, você pode fazer o seguinte para mantê-las SECAS .

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
fonte
101
app.get(["/foo", "/foo*"], /* function */);pode ser preferencial também!
Chris Foster
9
A passagem em uma série de strings também é preferencial para mim. Infelizmente: passar uma matriz para app.VERB () está obsoleto e será removido no 4.0
CodeWarrior
10
A passagem de uma série de strings foi restaurada no Expresso 4.9.1.
Pete TNT
30

O roteador de conexão agora foi removido ( https://github.com/senchalabs/connect/issues/262 ), o autor afirmando que você deve usar uma estrutura em cima de conectar (como Express) para roteamento.

O Express atualmente trata app.get("/foo*") como app.get(/\/foo(.*)/), eliminando a necessidade de duas rotas separadas. Isso está em contraste com a resposta anterior (referindo-se ao roteador de conexão agora removido), que afirmou que " *em um caminho é substituído por .+".

Update: Express agora usa o módulo "path-to-regexp" (desde Express 4.0.0) que mantém o mesmo comportamento na versão atualmente referenciada. Não está claro para mim se a versão mais recente desse módulo mantém o comportamento, mas por enquanto esta resposta permanece.

Johann
fonte
Portanto, devemos usar. + Ou *?
Tyler Langan
2
Use /\/foo(.+)/se quiser fazer a correspondência /fooseguida por um ou mais caracteres e /foo*ou /\/foo(.*)/se quiser fazer uma correspondência /fooseguida por zero ou mais caracteres.
Johann
12

Não é necessário ter duas rotas.

Basta adicionar (/*)?no final de sua pathcorda.

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

Aqui está um exemplo funcional, fique à vontade para copiar e colar em um arquivo .js para executar com o node e brincar com ele em um navegador (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!'))
Somo S.
fonte
9

No array, você também pode usar variáveis ​​passando para req.params:

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

Para aqueles que estão aprendendo node / express (assim como eu): não use o roteamento curinga, se possível!

Eu também queria implementar o roteamento para GET / users /: id / qualquer coisa usando o roteamento curinga. Foi assim que cheguei aqui.

Felizmente, também encontrei este artigo: http://www.jongleberry.com/wildcard-routing-is-an-anti-pattern.html

Saúde, Robert

Throbi
fonte
2
Link atualmente morto. Talvez fosse o mesmo que: jonathanong.github.io/wildcard-routing-is-an-anti-pattern.html
Ron Burk
@RonBurk seu url parece estar morto também .. Como posso ter um caractere curinga opcional após um parâmetro nomeado? "/ algo /: id (/ *)?" não funciona ..
Soichi Hayashi
Provavelmente ainda estará no cache do Google por um tempo: webcache.googleusercontent.com/…
Ron Burk
Existe uma alternativa para o roteamento curinga se eu não tiver ideia do que vem depois da parte inicial do URL?
Michael
1
Aqui está o republicado: Wildcard Routing é um
Antipadrão