Redirect

基於路徑的 Haproxy 重定向

  • December 18, 2018

類似於HAProxy reqrep remove URI on backend request

以下問題適用於我們。

我們有一些應用程序在一個域之外以不同的上下文根執行。然而,並非所有 url 的客戶端都被更改了。

如果請求與舊路徑匹配,我想在 haproxy 中使用 301 重定向進行重定向。

舉個例子http://example.com/abchttp://example.com/def

...
frontend https
 bind *:{{ proxy_port }} ssl crt /etc/haproxy/bundle_dh.pem ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4 no-sslv3
 http-request set-header X-Forwarded-Proto https if { ssl_fc }
 http-request set-header X-Forwarded-Port %[dst_port]

 acl has_legacy_abc path_beg /abc
 acl has_legacy_def path_beg /def
 redirect location 301 https://abcdomain.com/{PATH_WITHOUT_ABC} if { has_legacy_abc }
 redirect location 301 https://defdomain.com/{PATH_WITHOUT_ABC} if { has_legacy_def }

 use backend abc_backend if { hdr(Host) -i abcdomain.com }
 use backend def_backend if { hdr(Host) -i defdomain.com }
...

問題是如何在重定向中保留路徑。我可以做一個絕對重定向。

看起來,reqrep但這似乎是在傳遞到後端之前更改請求。我想告訴所有訪問者他們應該去新域。

這可以使用一些像這樣的臨時標題來完成,插入在您的acl定義和use_backend關鍵字之間:

http-request set-header X-Location-Path %[capture.req.uri] if has_legacy_abc OR has_legacy_def

http-request replace-header X-Location-Path [^/]+/(.*) \1 if has_legacy_abc OR has_legacy_def

http-request redirect location https://abcdomain.com/%[hdr(X-Location-Path)] if has_legacy_abc
http-request redirect location https://defdomain.com/%[hdr(X-Location-Path)] if has_legacy_def

根據您的域/路徑的實際配置和所需的重定向,甚至可以將其全部折疊成一組指令,如下所示:

...
frontend https
 bind *:{{ proxy_port }} ssl crt /etc/haproxy/bundle_dh.pem ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4 no-sslv3
 http-request set-header X-Forwarded-Proto https if { ssl_fc }
 http-request set-header X-Forwarded-Port %[dst_port]

 acl has_legacy path_beg /abc /def

 http-request set-header X-Location-Path %[capture.req.uri] if has_legacy
 http-request set-header X-Location-Host %[capture.req.uri] if has_legacy

 http-request replace-header X-Location-Host /([^/]*)/ \1 if has_legacy
 http-request replace-header X-Location-Path [^/]+/(.*) \1 if has_legacy

 http-request redirect location https://%[hdr(X-Location-Host)]domain.com/%[hdr(X-Location-Path)] if has_legacy_abc

 use backend abc_backend if { hdr(Host) -i abcdomain.com }
 use backend def_backend if { hdr(Host) -i defdomain.com }
...

如果路徑和域的數量很大,您可以使用映射(其中鍵是路徑,值是目標主機)來進一步簡化事情。

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