2016-07-02 4 views
2

В соответствии с различными документами и блогами, а также this question и другими, я знаю, что можно проверять параметры маршрута с помощью регулярных выражений. Это, однако, был я искал примерно в полтора часа:Регулярное выражение для маршрутов маршрута в Express.js

app.get('/api/:url(/^http:\/\/(.+?)\.(.+?)$/)', (req, res) => { 
    // do stuff with req.params.url 
}); 

Где каждый раз, когда я запускаю сервер локально и введите localhost://8000/api/http://www.google.com, ответ Cannot GET /new/http://www.google.com

Я знаю, что регулярное выражение делает то, что Я хочу, чтобы это было сделано, потому что:

/^http:\/\/(.+?)\.(.+?)$/.test('http://www.google.com'); 

... возвращает true.

Я также попытался изменить строку маршрута, чтобы выглядеть ...

'/api/:url(^http:\/\/(.+?)\.(.+?)$)' 

'/api/:url(http:\/\/(.+?)\.(.+?))' 

'/api/:url/^http:\/\/(.+?)\.(.+?)$/' 

И несколько других форматов, которые выглядят ничего отдаленно похожий на примеры, приведенных в переполнению стека потоков и блогах (Документы Экспресса имеют абсолютно нет примеров регулярного выражения, используемого вне параметра первого маршрута). Возможно, есть некоторые ограничения форматирования, о которых я не знаю, или ограничение на поддержку RegExp в Express? Было бы здорово, если бы документы вообще ничего не сказали.

Я ценю любую помощь, которую я могу получить здесь.

+0

Это опечатка или у вас есть «localhost», определяемый как протокол? Разве это не должно быть «http: // localhost: 8000/api/...»? –

+0

Это именно то, что я помещаю в адресную строку браузера, на самом деле неважно, включаю ли я протокол или нет. Независимо от того, о чем я спрашивал. –

+0

Мне было любопытно, спасибо. –

ответ

5

Ваше регулярное выражение неправильно, за то, что вы пытаетесь achiev е.

TL; DR Используйте этот один:

app.get('/api/:url(https?:\/\/?[\da-z\.-]+\.[a-z\.]{2,6}\/?)', (req, res) => { 
}); 

Некоторые пояснения:

Во-первых, path-to-regexp модуль используется курьерским делает именно то, что говорит его название: преобразует путь к регулярное выражение. Таким образом, якоря ^ и $ либо являются незаконными, либо могут быть интерпретированы по-разному, если они размещены внутри вашего содержимого :url() (path-to-regexp уже использует их). Кроме того, не включайте косые черты, используемые в JavaScript для идентификации объектов RegExp, а только содержимое выражения.

Вот как express видит ваши регулярные выражения:

path: '/api/:url(/^http://(.+?).(.+?)$/)' 
regexp: /^\/api\/(?:(\/^http:\/\/(?:\.+?))\.(\.+?)$\/)\/?$/i 

path: '/api/:url(^http://(.+?).(.+?)$)' 
regexp: /^\/api\/(?:(^http:\/\/(?:\.+?))\.(\.+?)$)\/?$/i 

path: '/api/:url(http://(.+?).(.+?))' 
regexp: /^\/api\/(?:(http:\/\/(?:\.+?))\.(\.+?))\/?$/i 

path: '/api/:url/^http://(.+?).(.+?)$/ 
regexp: /^\/api\/(?:([^\/]+?))\/^http:\/\/(?:\.+?)\.(\.+?)$\/?$/i 

И, используя фрагмент кода, как это, вы можете увидеть, что ни один матч:

const url = 'http://www.google.com'; 
for (let layer of app._router.stack) { 
    if (layer.name === 'bound dispatch') { 
    console.log(layer.regexp + ': matches', url, '=', layer.regexp.test(url)); 
    } 
} 

Также желательно избегать использования захваченным в уже именованном захвате.

Пример (обратите внимание на дополнительные скобки вокруг схемы URI, и как они изменяют значение req.params.url):

app.get('/api/:url((https?:\/\/)?[\da-z\.-]+\.[a-z\.]{2,6}\/?)', (req, res) => {}) 

> req.params: { '0': 'http://', url: 'http://' } 

Позже изменения: Обратите внимание, что весь этот пост только строка маршрутов, которые содержат регулярное выражение внутри, а не маршруты, определенные с помощью объектов RegExp.

+0

Это хорошее объяснение. +1 для подключения к 'path-to-regexp', мне это нужно. –

0

Попробуйте использовать двойные кавычки

app.get('/api/:url(/^http:\\/\\/(.+?)\\.(.+?)$/)', ... 
+0

Все, что происходит, это удаление символов обратной косой черты. Эти символы обратной косой черты были помещены туда, чтобы избежать символов прямой косой черты, чтобы соответствовать правильному URL-адресу. –

+0

Хех, это моя ошибка :) Предлагайте другой путь: '/api/:url(http://*\.*)' –

+0

humm. Это работает. Любая подсказка, почему эта работа работает, в то время как другое точное Regex не работает в этом контексте? –

0

Я не думаю, что вы можете заставить его работать с именованными параметрами, но вы можете передать регулярное выражение непосредственно:

app.get(/^\/api\/http:\/\/(.+?)\.(.+?)$/, ...); 

Это даст (как req.params):

{ '0': 'www', '1': 'google.com' }