Parece não haver um built-in para isso, mas é feito facilmente com a integração Lua no HAProxy 1.6 e posterior.
Crie um arquivo Lua, digamos /etc/haproxy/lua/url_escape.lua
.
Eu encontrei alguns exemplos online de url-escaping ("codificação") em Lua, mas nenhum deles que eu encontrei em uma pesquisa superficial parecia ser compatível com UTF-8. Então, eu escrevi isto:
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);
Configure o HAProxy para carregar isso, na seção global
de /etc/haproxy.cfg
:
global
lua-load /etc/haproxy/lua/url_escape.lua
Agora, você tem um conversor chamado lua.url_escape
, que funciona como outros conversores - é adicionado com ,
ao final da expressão que fornece sua entrada.
http-request set-query ref=%[req.hdr(Referer),lua.url_escape]&%[query]
Teste:
curl -v http://example.com/my-page.html?lol=cat -H 'Referer: http://example.org/cats/Shrödinger.html'
O pedido visto pelo back-end:
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
é corretamente escapado aqui com ö (U + 00D6) tendo dois bytes em Shr%C3%B6dinger
. Caracteres de 3 e 4 bytes também parecem ser tratados corretamente. Seqüências de bytes com o bit alto que não correspondem a caracteres UTF-8 válidos também serão escapadas.
Observe que, se você estiver registrando a string de consulta com HAProxy, a consulta modificada nunca será registrada - a solicitação original é o que a torna na saída de log.