我有一个复杂的 Apache 配置,它主要只执行 ProxyPassReverse,这似乎很愚蠢,所以我一直在将其转换为 haproxy。这主要使事情变得更加简单和清晰;耶。例外是复杂的 RewriteRule 和 RedirectMatch 之类的东西。特别是,我有这些:
RewriteRule ^(?:/l?mw)+/(.*\.php.*)$ https://mw-live.lojban.org/$1 [R=301,L]
RewriteRule ^(?:/l?mw)+/(.*)$ https://mw-live.lojban.org/papri/$1 [R=301,L]
这里的目的是将请求重定向到例如 /lmw/mw/lmw/foo.php 到 /foo.php,将 /mw/lmw/mw/MyPage 重定向到 /papri/MyPage(是的,这些 URL 很奇怪;该网站的旧版本存在一些重定向问题)。
据我所知,正确的做法是不是在 haproxy 中执行此操作,并使用后端 Web 服务本身。我询问这个问题是为了防止我遗漏了什么,但看起来在后端 Web 服务上执行此类操作确实比在 haproxy 中执行效果好得多。
我在 haproxy 中尝试执行此操作时遇到两个问题:
我找不到让 haproxy 记录其自身执行的重定向的方法。我已告诉 haproxy 显示 Location 响应标头,但它仅显示来自后端服务器的重定向:
capture response header Location len 128
在 haproxy 中执行此操作的方法很笨拙。我发现两种似乎可行的方法:
# Old URL formats; trim leading "/mw" and "/lmw" when the target is a php file http-request redirect code 301 location http://%[hdr(host)]%[url,regsub(^/lmw,,g)] if { path_beg /lmw } { path_sub .php } http-request redirect code 301 location http://%[hdr(host)]%[url,regsub(^/mw,,g)] if { path_beg /mw } { path_sub .php } # Old URL formats; trim leading "/mw" and "/lmw" http-request redirect code 301 location http://%[hdr(host)]/papri%[url,regsub(^/lmw,,g)] if { path_beg /lmw } http-request redirect code 301 location http://%[hdr(host)]/papri%[url,regsub(^/mw,,g)] if { path_beg /mw } http-request redirect code 301 location http://%[hdr(host)]/papri%[url,regsub(^/papri/lmw,,g)] if { path_beg /papri/lmw } http-request redirect code 301 location http://%[hdr(host)]/papri%[url,regsub(^/papri/mw,,g)] if { path_beg /papri/mw }
此方法的问题在于,除了代码很长之外,它还会产生一系列重定向,重复将每个 URL 重定向到少一个 /mw 或其他内容的 URL。
另一个是在前端有这个:
use_backend mw-live-back-old-with-php if { hdr_beg(host) -i mw-live. } { path_reg ^/l?mw.*\.php }
use_backend mw-live-back-old-without-php if { hdr_beg(host) -i mw-live. } { path_reg ^/l?mw }
然后是与它配合使用的这些特殊后端:
backend mw-live-back-old-with-php
http-request replace-path ^(?:/l?mw)+/(.*\.php.*)$ /\1
http-request redirect prefix / code 301
backend mw-live-back-old-without-php
http-request replace-path ^(?:/l?mw)+/(.*) /papri/\1
http-request redirect prefix / code 301
这种方法的问题在于还超级长,但仅为此创建后端似乎也很愚蠢。
你认为有用的东西,是我偷来的https://fromanegg.com/post/2014/12/05/how-to-rewrite-and-redirect-with-haproxy/,将这些行作为通用后端的一部分。
http-request replace-path ^(?:/l?mw)+/(.*\.php.*)$ /\1 if { path_reg ^/l?mw.*\.php }
http-request redirect prefix / code 301 if { path_reg ^/l?mw.*\.php }
http-request replace-path ^(?:/l?mw)+/(.*)$ /papri/\1 if { path_reg ^/l?mw }
http-request redirect prefix / code 301 if { path_reg ^/l?mw }
这会失败,因为重定向从未触发,因为当我们到达重定向行时,path_reg 不再匹配。
所以。
我是否遗漏了什么,或者我真的应该将这种复杂性转移到后端网络服务?
答案1
据我所知,正确的方法是不要在 haproxy 中执行此操作,而是使用后端 Web 服务本身。
太棒了。这里没必要再重新发明轮子了。