HAProxy reqrep remove URI on backend request に似ています。
以下の懸念事項が適用されます。
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
ですが、これはバックエンドに渡す前にリクエストを変更するためのようです。新しいドメインに移動する必要があるすべての訪問者に伝えたいと思います。
これは、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 }
...
パスとドメインの数が膨大な場合は、 maps (キーはパス、値は宛先ホスト)を使用して、さらに単純化できます。
私は同じ問題を抱えており、私がより良いと思う別の解決策を見つけました。この他のソリューションは、バージョン1.6以降のhaproxyでうまく機能します。 http-request and 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