如何使用 apache httpd 作为其他 Web 服务器的前端? 另一个小问题

问题描述

我想做什么

我想运行 Apache httpd (2.4.x) 作为 Apache tomcat (9.0.x) 和 Elasticsearch 服务器的前端。

例如,用户应该看到

http://localhost/tomcat/

内部转发到

http://localhost:8080/

例如

http://localhost/tomcat/manager/status(由 httpd 外部提供)

取自

http://localhost:8080/manager/status(内部来自 Tomcat)

我做了什么

mod_proxy、mod_proxy_http、mod_rewrite 被激活。

在 httpd.conf 中我添加

ProxyPass /tomcat http://localhost:8080
ProxyPassReverse /tomcat http://localhost:8080

或者替代

<Location "/tomcat">
    ProxyPass http://localhost:8080/
    ProxyPassReverse http://localhost:8080/
</Location>

什么不起作用

http://localhost/tomcat/ 正确提供预期页面。但是,该页面上的链接不会调整为新的基本 URL。

例如,页面包含 <a href="/docs/">Documentation</a>

点击该链接转到 应该去http://localhost/tomcat/docs 但指向http://localhost/docs

请注意,如果可能,我想在 Apache httpd 端使用解决方案(而不是重新配置 Tomcat),因为稍后我想对 Elasticsearch 后端使用相同的机制。

一个小问题

省略尾部斜杠时 http://localhost/tomcat 转发适用于 HTML 页面本身,但不适用于嵌入的资源,例如,Tomcat 徽标应检索为 http://localhost/tomcat/tomcat.svg -> http://localhost:8080/tomcat.svg 而是指向 http://localhost/tomcat.svg 未翻译,因为它不再与位置模式匹配。

解决方法

但是,该页面上的链接不会调整为新的基本 URL。

这是您配置中的主要问题:Web 应用程序通常生成绝对 URI 路径,如 /manager/images/tomcat.svg,而不是相对 URI 路径,如 images/tomcat.svg。它们使用 HttpServletRequest#getContextPath 检索部署路径 (/manager)。他们无法知道自己正在从另一条路径代理。

这就是为什么 Web 应用程序的原始 URL 和代理 URL 应该保持相同的 URI 路径的原因。在您的情况下,您应该在 /tomcat/manager 部署 Tomcat 管理器。这可以通过多种方式完成:

  • 如果您的 Tomcat Manager 应用程序位于 <Host>应用程序库 ($CATALINA_BASE/webapps) 中,请将目录重命名为 tomcat#manager(这通常发生在 Windows ),
  • 如果您的 Tomcat 管理器应用程序在 <Host>应用程序基础之外,请将上下文文件(在 $CATALINA_BASE/conf/Catalina/<host_name> 中)从 manager.xml 重命名为 {{ 1}}(这发生在像 Debian 这样的 Linux 发行版中),
  • 如果您在 tomcat#manager.xml 中定义应用程序上下文(不推荐),您可以使用 server.xml 元素的 path 属性。

数字符号 <Context> 将转换为 #

在 Apache 方面将 / 指令更改为:

ProxyPass