如何使用反向代理正确处理相对 URL

如何使用反向代理正确处理相对 URL

我在 Apache 中有一个反向代理设置,如下所示:

服务器 A 的地址为 www.example.com/folder 是反向代理服务器。

它映射到:服务器 B,地址为 test.madeupurl.com

这种方法可行。但我遇到的问题是,在 www.example.com/folder 上,所有相对链接都是 www.example.com/css/examplefilename.css 格式,而不是 www.example.com/folder/css/examplefilename.css

我该如何解决?

到目前为止我的反向代理在服务器 A(www.example.com)上有以下内容:

<Location /folder>
    ProxyPass  http://test.madeupurl.com
    ProxyPassReverse http://test.madeupurl.com
</Location>

答案1

Apache ProxyPassRewrite 不会重写从http://test.example.com,只有标题(例如重定向到 404 页面等)。

有多种替代方案:

)重写内部应用程序以使用相对路径而不是绝对路径。../css/style.css/css/style.css

)在同一个子目录中重新部署内部应用程序,/folder而不是在 test.example.com 的根目录中。

)一和二通常不太可能发生...如果你很幸运,内部应用程序只使用两个或三个子目录而这些在你的主网站上是未使用的,只需编写一堆 ProxyPass 行:

# Expose Internal App to the internet.
ProxyPass /externalpath/  http://test.example.com/
ProxyPassReverse /externalpath/  http://test.example.com/
# Internal app uses a bunch of absolute paths. 
ProxyPass /css/  http://test.example.com/css/
ProxyPassReverse /css/  http://test.example.com/css/
ProxyPass /icons/  http://test.example.com/icons/
ProxyPassReverse /icons/  http://test.example.com/icons/

)为内部应用程序创建一个单独的子域,并简单地反向代理所有内容:

<VirtualHost *:80>
   ServerName app.example.com/
   # Expose Internal App to the internet.
   ProxyPass /  http://test.internal.example.com/
   ProxyPassReverse /  http://test.internal.example.com/
</VirtualHost>

) 有时开发人员完全没有头绪,他们的应用程序不仅生成绝对 URL,甚至还在 URL 中包含主机名部分,生成的 HTML 代码如下所示:<img src=http://test.example.com/icons/logo.png>

A) 您可以使用水平分割 DNS 和方案 4 的组合解决方案。内部和外部用户都使用 test.example.com,但您的内部 DNS 直接指向 test.example.com 服务器的 IP 地址。对于外部用户,test.example.com 的公共记录指向您的公共 Web 服务器的 IP 地址www.example.com然后您可以使用解决方案4。

)实际上,你可以让 apache 不仅代理对 test.example.com 的请求,还可以重写响应主体才会将其传输给您的用户。(通常代理仅重写 HTTP 标头/响应)。apache 2.2 中的 mod_substitute。我尚未测试它是否能与 mod_proxy 很好地叠加,但也许以下方法可行:

<Location /folder/>
  ProxyPass http://test.example.com/
  ProxyPassReverse http://test.example.com/ 
  AddOutputFilterByType SUBSTITUTE text/html
  Substitute "s|test.example.com/|www.example.com/folder/|i" 
</Location>

后期编辑

) 有时开发人员会专门为应用程序位于反向代理后面的部署提供特殊的应用程序设置。然后可以将应用程序配置为生成自引用 URL,其中包含用户正在/应该使用的协议、站点名称和 URI 路径,而不是然后是主机名、协议和/或应用程序检测到的 URI。期待像 这样的术语external URLsite URL那么您不需要在 Apache 中解决任何问题。

答案2

作为补充布赖恩的答案,如果你选择解决方案(3)“ProxyPass”,你可能还必须使用mod_proxy_html重写 HTML 页面中的某些 URL。

参见如何使用反向代理正确处理相对 URL举一些例子。

作为一个应用示例,下面介绍如何使用ProxyHTMLURLMap规则配置 Apache,以便将所有内容转发到您的域名.com/pad你的Etherpad在端口 9001 本地运行的实例:

<Location /pad>
  ProxyPass http://localhost:9001 retry=0
  # retry=0 => avoid 503's when restarting etherpad-lite
  ProxyPassReverse http://localhost:9001
  SetOutputFilter proxy-html
  ProxyHTMLURLMap http://localhost:9001
</Location>
RewriteRule ^/pad$ /pad/ [R]

答案3

您可以使用以下方式创建反向代理:
1.安装 mod_proxy_html

    yum install mod_proxy_html
  1. 加载 mod_proxy_html 模块

    LoadModule proxy_html_module modules/mod_proxy_html.so
    
  2. 并使用以下设置

    ProxyRequests off  
    ProxyPass /folder/  http://test.madeupurl.com  
    ProxyHTMLURLMap http://test.madeupurl.com  /folder  
    
    <Location /folder/>  
        ProxyPassReverse /  
        ProxyHTMLEnable On  
        ProxyHTMLURLMap  /  /folder/  
        RequestHeader    unset  Accept-Encoding  
    </Location>  
    

希望这有帮助。

相关内容