Haproxy

查詢字元串的 HAProxy 編碼 url

  • September 3, 2021

我有一個系統需要在多個重定向中保留原始引用。為了實現這一點,我試圖將引用者寫入 URL 查詢字元串。

我已經開始工作了(有點)。

http-request set-query ref=%[req.hdr(Referer)]&%[query]

唯一的問題是必須對查詢字元串中的 URL 進行編碼。不幸的是,HAProxy 只有一個 url_dec 函式。

有什麼簡單的方法可以對 URL 進行編碼嗎?

似乎沒有內置的,但通過 HAProxy 1.6 及更高版本中的 Lua 集成很容易完成。

創建一個 Lua 文件,比如說/etc/haproxy/lua/url_escape.lua.

我在 Lua 中找到了一些關於 url-escaping(“編碼”)的線上範例,但我在粗略搜尋中發現的這些範例似乎都不是 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);

global在以下部分配置 HAProxy 以載入它/etc/haproxy.cfg

global
   lua-load /etc/haproxy/lua/url_escape.lua

現在,您有一個名為 的轉換器lua.url_escape,它與其他轉換器一樣工作——它在,提供其輸入的表達式的末尾添加了 a。

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://serverfault.com/questions/910336