I have a system that needs to preserve the original referer over multiple redirects. To achieve this I'm trying to write the referer to the URL query string.
I already got that working (somewhat).
http-request set-query ref=%[req.hdr(Referer)]&%[query]
The only problem is that URLs in the querystring have to be encoded. Unfortunately HAProxy only has a url_dec function.
Is there any easy way in which I can encode the URL?
Похоже, что для этого нет встроенного модуля, но это легко сделать с помощью интеграции Lua в HAProxy 1.6 и более поздних версиях.
Создайте файл Lua, скажем /etc/haproxy/lua/url_escape.lua
.
Я нашел в Интернете несколько примеров экранирования URL-адресов ("кодирования") в Lua, но ни один из них, который я обнаружил при беглом поиске, не был UTF- 8 в курсе. Итак, я написал следующее:
function url_escape(str)
local escape_next = 0;
local escaped = str:gsub('.',function(char)
local ord = char:byte(1);
if(escape_next > 0) then
escape_next = escape_next - 1;
elseif(ord <= 127) then -- single-byte utf-8
if(char:match("[0-9a-zA-Z%-%._~]")) then -- only these do not get escaped
return char;
elseif char == ' ' then -- also space, becomes '+'
return '+';
end;
elseif(ord >= 192 and ord < 224) then -- utf-8 2-byte
escape_next = 1;
elseif(ord >= 224 and ord < 240) then -- utf-8 3-byte
escape_next = 2;
elseif(ord >= 240 and ord < 248) then -- utf-8 4-byte
escape_next = 3;
end;
return string.format('%%%02X',ord);
end);
return escaped;
end;
core.register_converters('url_escape',url_escape);
Настройте HAProxy для его загрузки в разделе global
в /etc/haproxy.cfg
:
global
lua-load /etc/haproxy/lua/url_escape.lua
Теперь у вас есть конвертер под названием lua.url_escape
, который работает так же, как и другие конвертеры - он добавлен с помощью ,
в конец выражения, которое предоставляет его входные данные.
http-request set-query ref=%[req.hdr(Referer),lua.url_escape]&%[query]
Тест:
curl -v http://example.com/my-page.html?lol=cat -H 'Referer: http://example.org/cats/Shrödinger.html'
Запрос, который видит внутренняя часть:
GET /my-page.html?ref=http%3A%2F%2Fexample.org%2Fcats%2FShr%C3%B6dinger.html&lol=cat HTTP/1.1
User-Agent: curl/7.35.0
Host: example.com
Accept: */*
Referer: http://example.org/cats/Shrödinger.html
Shrödinger
здесь правильно экранирован с помощью ö (U + 00D6), имеющего два байта в Shr% C3% B6dinger
. 3- и 4-байтовые символы также обрабатываются правильно. Последовательности байтов со старшим битом, которые не соответствуют допустимым символам UTF-8, также будут экранированы.
Обратите внимание, что если вы регистрируете строку запроса с помощью HAProxy, измененный запрос никогда не регистрируется - исходный запрос что попадает в вывод журнала.
ОБНОВЛЕНИЕ:
Теперь есть встроенный конвертер: https://www.haproxy.com/documentation/hapee/2-2r1/onepage/#url_enc
Вы можете использовать его в директиве http-request
следующим образом:
http-request redirect location https://example.com/login?r=%[url,url_enc()] if !{ req.hdr(x-consumer-username) -m found }
В этом примере исходный запрошенный URL закодирован в URL и добавлен в строку запроса по ключу r
.
Исходный ответ:
Ребята из HAProxy создали раздел блога, посвященный именно этому варианту использования:
https://www.haproxy.com/blog/5-ways-to-extend-haproxy-with. -lua/#converters
Похоже, что это должно быть встроено в ИМО.