Я пытаюсь исправить проблему с параметром 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.