【问题标题】:AJP proxy that maps internal servlet name to a different external name将内部 servlet 名称映射到不同的外部名称的 AJP 代理
【发布时间】:2011-01-15 06:00:00
【问题描述】:

使用 apache2 我想为 Tomcat 服务器设置一个 AJP 代理,它将内部 servlet URL 映射到外部完全不同的 URL。目前我正在使用以下配置:

Apache2 配置:

<IfModule mod_proxy.c>
    ProxyPreserveHost on
    ProxyPass /external_name ajp://192.168.1.30:8009/servlet_name
    ProxyPassReverse /external_name ajp://192.168.1.30:8009/servlet_name
</IfModule>

注意external_nameservlet_name 是不同的。

Tomcat 6 配置:

<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />

但这不起作用。 Apache 似乎将 http 请求转发到 Tomcat。 但是 Tomcat 返回的 URL 和重定向仍然使用原始的 servlet_name,而 Apache 并没有将它们映射到 external_name

这对 AJP 有可能吗?如果不能,可以改用普通的 http 代理吗?

【问题讨论】:

    标签: apache tomcat ajp


    【解决方案1】:

    对我来说,这似乎会导致问题:

    ProxyPreserveHost on
    ProxyPass /external_name ajp://192.168.1.30:8009/servlet_name
    ProxyPassReverse /external_name http://192.168.1.30/servlet_name
    

    虽然这似乎有效:

    ProxyPreserveHost on
    ProxyPass /external_name ajp://192.168.1.30:8009/servlet_name
    ProxyPassReverse /external_name ajp://192.168.1.30:8009/servlet_name
    

    我不知道为什么,但它确实发生了。

    【讨论】:

    • 它们是一样的还是我错过了什么?
    • 不同,第二个 ProxyPassReverse 声明的 URL 以 AJP 开头,而不是第一个中的 HTTP。
    【解决方案2】:

    除了answer from Steven D. Majewski 还有一个问题。如果目标应用程序使用请求主机名来创建重定向(302 临时移动),它将无法与多个主机名一起使用。必须为每个名称创建多个配置,如下所示:

    ProxyPassReverse /external_name http://server.com/servlet_name
    ProxyPassReverse /external_name http://server.org/servlet_name
    ProxyPassReverse /external_name http://server.co.uk/servlet_name
    

    实际上ProxyPreserveHost on 必须解决这个问题,并将传入请求中的HOST 标头替换为ProxyPass 中指定的地址或IP。不幸的是,ProxyPreserveHost 似乎不适用于 ajp 连接器。我的配置中的 tomcat 仍然收到从浏览器获取的主机名,而不是用192.168.1.30 替换它。结果,基于浏览器的重定向仍然不适用于每个名称。

    以下配置也无法正常工作:-(

    # NOT WORKING !!!
    ProxyPassReverse /external_name http://%{HTTP_HOST}/servlet_name 
    

    解决方法是使用 http 而不是 ajp。

    ProxyPreserveHost on
    ProxyPass /external_name ajp://192.168.1.30:8009/servlet_name
    ProxyPassReverse /external_name http://192.168.1.30/servlet_name
    

    有人深入调查了吗?

    【讨论】:

      【解决方案3】:

      (一个迟到的答案,但我自己也遇到了这个问题。)

      使用 ajp: 的 ProxyPassReverse 似乎不起作用,因为从重定向返回的标头在 Location: 中没有 ajp: URL,它们有一个 http: URL。 ProxyPassReverse 只会导致匹配标头的重写,并且 该字符串与返回的内容不匹配。

      这应该可以工作(只要 Location: 字段使用该数字地址 而不是主机名。)

      ProxyPreserveHost on
      ProxyPass /external_name ajp://192.168.1.30:8009/servlet_name
      ProxyPassReverse /external_name http://192.168.1.30/servlet_name
      

      (您可以使用'curl -I'来检查重定向标头并进行调试。)

      请参阅this note,或使用 mod_proxy_html 的更多相关solution here 也用于重写网页中的 URL。

      【讨论】:

        【解决方案4】:

        在 Apache 和 Tomcat 之间映射不同的名称可能非常棘手,并且很大程度上取决于 Web 应用程序如何为响应构建其 url。

        基本上您的设置是正确的,但如果您的应用程序使用自己的 servlet_name 进行重定向和 url,ProxyPassReverse 将不会映射它们。

        如果您需要这种设置,请查看mod_proxy_html(Apache 3rd 方模块),它还将解析和重写内容,而不仅仅是作为 mod_proxy 的 url 和响应标头。

        【讨论】: