Назад | Перейти на главную страницу

HAproxy вызывает у меня проблемы с заменой регулярных выражений. Это ошибка или я что-то делаю неправильно?

Я пытаюсь исправить проблему с параметром URL-адреса путем принудительного кодирования URL-адреса на узле пути POST, что довольно часто встречается. На данный момент лучше всего исправить это на уровне прокси, пока не будет разработано лучшее решение ... но Haproxy вызывает у меня проблемы с этим, я также должен упомянуть, что на данный момент я застрял на Haproxy v1.5 ( который, насколько я могу судить, также исключает использование Lua из списка опций .. введенных в v1.6?).

Пример этого может быть таким ..

Обычно я получаю запрос POST в такой форме ..

http(s)://sub.domain.com/context/{context}/staticPath/location/{location}/material/{material} 

Так что на практике это может выглядеть примерно так ...

http://sub.domain.com/context/smith/staticePath/location/columbus/material/abc/123

Требуется следующее на другом конце ..

http://sub.domain.com/context/smith/staticePath/location/columbus/material/abc%2F123

Проблема в том, что abc / 123 - это отдельный материал, который должен больше походить на «abc% 2F123», где косая черта '/' изменяет фактический путь.

Я пытаюсь уловить это в прокси, я могу получить регулярное выражение для захвата того, что мне нужно, но кажется, что всякий раз, когда я пытаюсь использовать «косую черту» '/' в группе захвата и / или пытаюсь вернуть косую черту в заменить раздел, он прерывает перезапись.

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

В этом случае..

reqrep (\w+\s?)\/(material)\/(\w+\s?)\/(.*) \1\2\3%2f\4

Я могу заставить группы захвата снова собрать URL-адреса, но без разделителей пути ("/") между узлами пути.

Таким образом, он не заменяет, а просто отправляет исходный путь.

reqrep (\w+\s?)\/(material)\/(\w+\s?)\/(.*) \1\/\2\/\3%2f\4

Принимая такую ​​стратегию ...

reqrep (\w+\s?)(\/)(material)(\/)(\w+\s?)\/(.*) \1\2\3\4\5%2f\6

Еще одна стратегия, которую я пробовал, - это сохранить символы «/» в группах захвата, чтобы они могли появиться при замене, оставляя нежелательную «косую черту» не в группе захвата, как показано ниже.

reqrep (\w+\s?)(\/material\/)(\w+\s?)\/(.*) \1\2\3%2f\4

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

также..

Если я уберу пробел, то добавлю косую черту, это будет работать ближе .. например. \1\ /\2 но тогда я бы получил что-то вроде (например) location /material.. добавив пробел, как указано выше.

Паттерн, который я замечаю, заключается в том, что когда я пытаюсь добавить косые черты в группу захвата в регулярном выражении, это нарушает замену, заставляя меня дико гадать о таких вещах, как ... косые черты не экранируются, потому что они находятся в группе захвата? И почему я не могу просто вернуть их в замену как литералы? Это момент, когда я предполагаю, что, возможно, наткнулся на ошибку ... но также осознаю, что могу облажаться. Решение было разработано с использованием Nginx, но размещение экземпляра этого перед тем, что нам нужно, также не является самым практичным, если я могу заставить Haproxy сделать это, в основном потому, что мы уже используем Haproxy для довольно многих других вещей. уже.

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

Это предложение, которое я сделал в комментариях, похоже, делает почти правильную вещь:

reqrep ^([^\ :]+)(\ ?/.+/material/)(.+)/(.+)(\ .+)$ \1\2\3\4%2f\5

Фактически я положил \4 на изнанке %2f. Я также неправильно сделал пространство в начале второй группы захвата необязательным, что не нарушает регулярное выражение, но не является технически правильным.

Это правильная форма:

reqrep ^([^\ :]+)(\ /.+/material/)(.+)/(.+)(\ .+)$ \1\2\3%2f\4\5

Это проблема с reqrep - вы настраиваете непосредственно первую строку HTTP-запроса. Мощно, но утомительно.

Разбивая это:

^ Всегда привязывайте узор к началу строки.

([^\ :]+) Это HTTP-глагол (GET, POST, и т.д.). Он не должен содержать пробелов и двоеточия. Это группа захвата 1.

(\ /.+/material/) За глаголом должен следовать пробел, ведущая косая черта (косая черта в прямом направлении не требует escape-косой черты в регулярных выражениях HAProxy), один или несколько символов, затем / material / ... это группа захвата 2.

(.+) Первая часть того, что мы хотим разделить на / это группа захвата 3 ... и действительно, это было бы правильнее написать ([^/]+) хотя большинство потенциальных несоответствий предотвращается за счет места, которое нам требуется в группе 5 ниже.

/ косая черта, которую мы хотим удалить

(.+) Часть URL-адреса после / группа захвата 4

(\ .+) пробел, за которым следует 1 или несколько символов, которые собираются захватить HTTP/1.x в конце строки запроса как группа захвата 5.

$ привязан к концу линии.

Затем соедините их все вместе.

\1\2\3%2f\4\5


HAProxy 1.6 справляется с этим более элегантно с помощью встроенного интерпретатора Lua, а также конвертера под названием regsub() (хотя это очень просто - только подстановки, без групп захвата, но это хорошо для разделения строк) и определяемые пользователем переменные, в которые вы можете «спрятать» небольшие фрагменты данных во время обработки запроса. Это также позволяет вам использовать http-request set-path и имеет path fetch для чтения и записи пути изолированно от остальной части URL-адреса и без прямой настройки буфера HTTP-запроса с помощью регулярного выражения. Большей части или всего этого нет в версии 1.5.