在 Chrome 中,此配置会导致无限重定向循环,并且在我尝试过的所有其他浏览器中,请求https://www.example.com/servlet/foo导致重定向到https://www.example.com/foo/代替https://www.example.com/servlet/foo/然而,这仅当我在请求 url 末尾不包含尾随 / 时才会发生(即http://www.flightboard.net/servlet/foo/工作正常)。
<VirtualHost *:80>
# ...
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteCond %{REQUEST_URI} ^/servlet(/.*)?$
RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L]
</VirtualHost>
<VirtualHost *:443>
# ...
ProxyPass /servlet/ ajp://localhost:8009/
ProxyPassReverse /servlet/ ajp://localhost:8009/
</VirtualHost>
端口 443 上的虚拟主机没有可能导致问题的重写规则,引用的 tomcat 上下文不会发送任何重定向,如果我将 ProxyPass 和 ProxyPassReverse 指令更改为:
ProxyPass / ajp://localhost:8009/
ProxyPassReverse / ajp://localhost:8009/
一切正常(除了 www.example.com 上的所有内容都被传递给代理,这不是我想要的行为)。我相当确定这是我的代理设置配置方式的问题,因为我确实记录了来自 apache 的所有重写输出,而且全部正确。
答案1
从 mod_proxy_ajp 切换到 mod_proxy_http 似乎可以解决这个问题。
ProxyPass /servlet/ http://localhost:8080/
ProxyPassReverse /servlet/ http://localhost:8080/
不幸的是,这样做的副作用是不会传递远程连接的 IP 地址。另一种方法是添加重写规则以匹配末尾缺少斜杠的 URL:
RewriteCond %{REQUEST_URI} ^/servlet/[^/]+$
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI}/ [R=301,L]
答案2
我不确定这是否是您的问题,但 ProxyPassReverse 不适用于 ajp: url。如果 Location: 标头匹配,ProxyPassReverse 会导致重写这些标头。重定向生成的标头具有 http: URL,而不是 ajp:
您应该能够使用:
ProxyPass /servlet/ ajp://localhost:8009/
ProxyPassReverse /servlet/ http://hostname/
即使用 ajp: 作为 tomcat 的代理,但使用 http: 匹配和重写重定向标头。返回的标头也可能具有服务器的真实主机名而不是 localhost。(尽管 localhost 适用于 ProxyPass )。您可以使用“curl -I”检查返回的标头以查看需要匹配的内容。
( 这个问题已经有几个月了,但我刚刚遇到了同样的问题,并且很难找到答案。)