2016-11-03 73 views
0

我想重新寫一個使用HAProxy的如寫的URL路徑參數的查詢字符串HAProxy的

http://ourdomain.com/hotels/vegas?cf=0 

http://ourdomain.com?d=vegas&cf=0 

URL。

我們使用使用

RewriteRule ^hotels/([^/]+)/?\??(.*)$ ?d=$1&$2 [QSA] 

我已經試過

reqrep ^([^\ :]*)\ /hotels/(.*)  \1\ /?d=\2 

與Apache做,而是說給我http://ourdomain.com?d=vegas?cf=0

而且

reqrep ^([^\ :]*)\ /hotels/([^/]+)/?\??(.*)  \1\ /?d=\2&\3 

只是給了我一個400錯誤。

這將是很好的做與acl的,但我不明白這是如何工作。

回答

1
reqrep ^([^\ :]*)\ /hotels/([^/]+)/?\??(.*)  \1\ /?d=\2&\3 

只給了我一個400錯誤。

([^/]+)如果後面的所有內容/?\??(.*)都是可選的,那麼就太貪婪了。它的重整要求的最後部分,導致400

記住,你正在使用什麼樣的數據:

GET /path?query HTTP/1.(0|1) 

更換([^/]+)([^/\ ]+)所以之後任何東西,包括空間將是由\3捕獲,而不是\2


更新:看來,上面是不是相當完美,因爲?的定位仍然不工作了。這個 - 和原始的400錯誤 - 用req[i]rep突出顯示了一些陷阱 - 這是非常低的請求消耗。

HAProxy 1.6引入了一些新的功能,使請求調整更清晰,這實際上是一個很好的例子來說明其中幾個。請注意,這些示例還使用匿名ACL,包裝在{}中。這些文檔似乎有點阻礙了這些 - 但這只是因爲當你需要測試同一組條件時(由於多種原因,命名ACL當然可以更容易重用),它們很難維護),但是它們'對於這樣的情況來說非常完美。請注意,由於配置解析器限制,大括號必須至少包含1個空格字符。

變量,作用域爲請求(一旦選擇後端就超出範圍),響應(僅在後端響應後才進入作用域),事務(從請求到響應的持久性,這些可以在到達後端之前使用,並且在響應返回時仍然在範圍內)或會話(在該連接期間,如果瀏覽器重新使用該連接,則在該瀏覽器的多個請求的範圍內)可用於隱藏值。

regsub()變換器取的先前值作爲它的輸入,並返回通過簡單的正則表達式替換傳遞該值。

如果路徑以/hotels/啓動時,捕捉路徑,洗滌出^/hotels/(與下一個逗號後出現的空字符串代替它),以及在名爲req.hotel請求變量藏匿它。的最http-request步驟

http-request set-var(req.hotel) path,regsub(^/hotels/,) if { path_beg /hotels/ } 

Processing在配置文件中的順序進行,所以,在下一條指令,當(且僅當),該變量具有一個值,我們爲了使用http-request set-path/參數清空路徑。測試變量是必要的,這樣我們就不會對每個請求都這樣做 - 只有/ hotels /纔會這樣做。這可能是因爲/hotels/本身可能是一個我們應該獨自離開的有效路徑,所以您實際上可能需要一些更類似if { path_reg /hotels/.+ }的東西。

http-request set-path/if { var(req.hotel) -m found } 

然後,我們使用http-request set-query設置查詢字符串通過連接req.hotel變量與&的值和原始查詢字符串,我們使用所述query獲得創建的值。

http-request set-query d=%[var(req.hotel)]&%[query] if { var(req.hotel) -m found } 

注意,query提取和http-request set-query都有一些神奇的行爲 - 他們照顧?的爲您服務。提取query不會返回它,並且http-request set-query不指望您提供它。這很有幫助,因爲我們可能需要能夠正確處理請求,不管?是否存在於原始請求中,而無需自行管理。

通過上述配置,GET /hotels/vegas?&cf=0 HTTP/1.1變爲GET /?d=vegas&cf=0 HTTP/1.1

如果初始查詢字符串是完全空的,GET /hotels/vegas HTTP/1.1變成GET /?d=vegas& HTTP/1.1。這看起來有點奇怪,但它應該是完全有效的。一個稍微複雜的配置來測試初始查詢字符串的存在可能會阻止,但我不認爲這是一個問題。因此,我們已經將1行配置變成了3,但我認爲這三行對於他們正在完成的事情更加直觀,並且它的確比精簡整個請求的起始行與正則表達式。在這裏,他們是一起有一些可選的空白:

http-request set-var(req.hotel) path,regsub(^/hotels/,) if { path_beg /hotels/ } 
http-request set-path/        if { var(req.hotel) -m found } 
http-request set-query d=%[var(req.hotel)]&%[query]  if { var(req.hotel) -m found } 
+0

謝謝。這給了我'd = vegas?cf = 0&'(從php中的$ _SERVER ['QUERY_STRING']'讀取)。 –

+0

啊,它確實如此。道歉,我發現了一個問題,並忽略了第二個問題。這正是我用眼球解析正則表達式所得到的結果。順便說一下,這是HAProxy> = 1.6?如果是這樣的話,有一些更乾淨的操作方法。 –

+1

是的,我們在HAProxy 1.6 :) - 清潔方法聽起來不錯。我設法找到了一些工作。我會發布我的正則表達式解決方案,但是會在任何一天將它換成更乾淨的方法! (我相信一個更清潔的解決方案對任何回來的人都有用)。無論如何,從我+1。 –

0

這是使用reqrep

acl is_destination path_beg /hotels/ 
reqrep ^([^\ :]*)\ /hotels/([^/\ \?]+)/?\??([^\ ]*)(.*)$  \1\ /?d=\2&\3\4 if is_destination 

我希望的是,ACL將刪除需要的一切運行正則表達式(因此一個可行的解決方案減輕負荷),但我不確定是這種情況。

+1

感謝@邁克爾 - sqlbot讓我99%的方式。 –

相關問題