Маршрутизация с использованием подстановочных знаков Express-js для покрытия всего, что находится под путем и включая путь

96

Я пытаюсь сделать так, чтобы один маршрут охватил все, /fooвключая /fooсебя. Я пробовал использовать эту /foo*работу для всего, кроме того, что она не подходит /foo. Обратите внимание:

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

Выходы:

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

Какие у меня варианты? Лучшее, что я придумал, - это маршрут, /fo*который, конечно, не очень оптимален, так как он слишком много совпадет.

Кит Сунде
источник
Если вы перехватываете все /foo*подобные маршруты, разве вы не хотите вместо этого использовать промежуточное ПО?
Raynos
3
Будьте осторожны с тем, что вы просите: /foo*совпадения, /foo/barно также совпадения, /foolishкоторые вы, вероятно, не планировали.
Wyck

Ответы:

112

Думаю, у вас будет 2 маршрута. Если вы посмотрите на строку 331 маршрутизатора подключения, * в пути заменяется на. +, Поэтому будет соответствовать 1 или более символам.

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

Если у вас есть 2 маршрута, которые выполняют одно и то же действие, вы можете сделать следующее, чтобы он оставался СУХИМ .

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
источник
104
app.get(["/foo", "/foo*"], /* function */);тоже может быть предпочтительным!
Крис Фостер
9
Для меня также предпочтительнее передавать массив строк. К сожалению: передача массива в app.VERB () устарела и будет удалена в версии 4.0
CodeWarrior
10
В Express 4.9.1 восстановлена ​​передача массива строк.
Pete TNT
30

Маршрутизатор подключения теперь удален ( https://github.com/senchalabs/connect/issues/262 ), автор заявляет, что для маршрутизации следует использовать фреймворк поверх подключения (например, Express).

В настоящее время Express обрабатываетapp.get("/foo*") как app.get(/\/foo(.*)/), что устраняет необходимость в двух отдельных маршрутах. Это контрастирует с предыдущим ответом (относящимся к теперь удаленному маршрутизатору подключения), в котором говорилось, что « *в пути заменяется на .+».

Обновление: Express теперь использует модуль «path-to-regexp» (начиная с Express 4.0.0), который поддерживает такое же поведение в текущей версии. Мне неясно, сохраняет ли последняя версия этого модуля такое поведение, но пока этот ответ остается в силе.

Иоганн
источник
Так что мы должны использовать. + Или *?
Тайлер Ланган,
2
Используйте, /\/foo(.+)/если вы хотите сопоставить, /fooза которым следует один или несколько символов, /foo*или /\/foo(.*)/если вы хотите сопоставить, /fooза которым следует ноль или более символов.
Иоганн
12

Нет необходимости иметь два маршрута.

Просто добавьте (/*)?в конец pathстроки.

Например, app.get('/hello/world(/*)?' /* ... */)

Вот полностью рабочий пример, не стесняйтесь копировать и вставлять его в файл .js для запуска с помощью node и играть с ним в браузере (или 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

В массиве вы также можете использовать переменные, передаваемые в req.params:

app.get(["/:foo", "/:foo/:bar"], /* function */);
DrDimedrol
источник
4

Для тех, кто изучает node / express (как и я): по возможности не используйте маршрутизацию с подстановочными знаками!

Я также хотел реализовать маршрутизацию для GET / users /: id / something с использованием маршрутизации с использованием подстановочных знаков. Вот как я сюда попал.

Подробнее: https://blog.praveen.science/wildcard-routing-is-an-anti-pattern/

Throbi
источник
3
Ссылка сейчас мертва. Возможно, это было то же самое, что и: jonathanong.github.io/wildcard-routing-is-an-anti-pattern.html
Рон Бурк
@RonBurk, ваш URL-адрес тоже кажется мертвым .. Как мне добавить дополнительный шаблон после именованного параметра? "/ что-то /: id (/ *)?" не работает ..
Соичи Хаяси
Вероятно, еще какое-то время будет в кеше Google: webcache.googleusercontent.com/…
Рон Бурк,
есть ли альтернатива маршрутизации с использованием подстановочных знаков, если я не знаю, что идет после начальной части URL-адреса?
Майкл
2
Вот переизданный вариант
Praveen Kumar