Linux

HAproxy 給我正則表達式替換的問題,這是一個錯誤還是我做錯了什麼?

  • December 7, 2016

我試圖通過在 POST 路徑的節點上強制進行 URL 編碼來更正 URL 參數問題,這在一定程度上是經常發生的。目前,最好在代理層解決這個問題,直到開發出更好的解決方案。但是 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

我也讀過,並看到一些正則表達式有空格並且替換有一些間距的例子。我可以通過在替換中使用一些間距來接近,但這會在最終結果中留下不需要的空格。

還..

如果我轉義一個空格,然後添加一個斜線,它似乎更接近.. ex。\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/)動詞後面必須跟一個空格、前導斜杠(在 HAProxy 正則表達式中,正斜杠不需要反斜杠轉義)、一個或多個字元,然後是 /material/ …這是擷取組 2。

(.+)我們要在 a 處拆分的第一部分是擷取組 3……實際上,儘管大多數潛在的不匹配都被我們在下面的第 5 組中所需的空間所阻止/,但這會更正確地編寫。([^/]+)

/我們要消除的斜線

(.+)之後的 URL 部分/是擷取組 4

(\ .+)一個空格,後跟 1 個或多個字元,它將HTTP/1.x在請求行的末尾作為擷取組 5 擷取。

$錨定到線的末端。

然後將它們全部重新組合在一起。

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


HAProxy 1.6 使用內置的 Lua 解釋器以及一個名為的轉換器regsub()(雖然它非常簡單——僅替換,沒有擷取組,但它對拆分字元串很有用)和使用者定義的變數,可以更優雅地處理這個問題。在處理請求時儲存“小數據塊。它還允許您使用http-request set-path並具有一個pathfetch 來讀取和寫入與 URL 的其餘部分隔離的路徑,而無需直接使用正則表達式調整 HTTP 請求緩衝區。大多數或所有這些東西不在 1.5 中。

引用自:https://serverfault.com/questions/818937