に似ているHAProxy reqrep はバックエンド リクエストで URI を削除します。
当社には以下の懸念事項が当てはまります。
1 つのドメインから異なるコンテキスト ルートで実行されているアプリケーションがあります。ただし、URL のすべてのクライアントが変更されたわけではありません。
リクエストがレガシー パスと一致する場合、haproxy で 301 リダイレクトを使用してリダイレクトしたいと思います。
例えばhttp://example.com/abc
、http://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
バックエンドに渡す前にリクエストを変更するためのもののようです。すべての訪問者に新しいドメインに移動するように伝えたいと思います。
答え1
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
ドメイン/パスの実際の構成と必要なリダイレクトによっては、次のようにすべてを 1 つのディレクティブ セットにまとめることも可能になる場合があります。
...
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 }
...
パスとドメインの数が膨大になる場合は、地図(キーはパス、値は宛先ホスト) を使用すると、さらに簡単になります。
答え2
私も同じ問題を抱えていましたが、より良い解決策を見つけました。この解決策はhaproxyのバージョン1.6以降でうまく機能します。http-request と regsub。
あなたの例を書き直すと:
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
acl has_legacy_abc path_beg /abc
acl has_legacy_def path_beg /def
http-request redirect code 301 location https://%[hdr(host)]%[url,regsub(^/abc,/newabc,)] if has_legacy_abc