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

Har*_*ker 66 linux reverse-proxy apache-2.2

我在 Apache 中有如下反向代理设置:

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

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

这种作品。但我遇到的问题是,在 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>
Run Code Online (Sandbox Code Playgroud)

HBr*_*ijn 104

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/
Run Code Online (Sandbox Code Playgroud)

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

<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>
Run Code Online (Sandbox Code Playgroud)

)有时候开发是完全没有头绪,而且有自己的应用不仅能产生绝对的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 的公共记录指向您的公共网络服务器 www.example.com 的 ip 地址,然后您可以使用解决方案 4。

B ) 您实际上可以让 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>
Run Code Online (Sandbox Code Playgroud)

  • 圣牛好答案。甚至还没有尝试过这些,只是想感谢您的撰写!帮助一百万。现在要测试其中的一些想法,并将很快回来报告:) (5认同)

Luc*_*mon 13

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

参见 对于一些示例,如何使用反向代理正确处理相对 url

作为一个应用示例,以下是如何使用ProxyHTMLURLMap规则配置 Apache ,将your-domain-name.com/pad中的所有内容转发到在端口 9001 上本地运行的Etherpad实例:

<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]
Run Code Online (Sandbox Code Playgroud)

  • 请注意,虽然 mod_proxy_html 仅包含在 Apache 2.4 及更高版本中,但上面的原始问题是针对 Apache 2.2 (3认同)
  • 如果您的内容是 PDF,则无需在其中重写 URL!除非您希望您的用户单击 PDF 中的链接来访问您网站的其他页面,但这听起来很棘手。要禁用 URL 重写,只需省略最后 2 个指令:`SetOutputFilter` 和 `ProxyHTMLURLMap`。 (2认同)

Tha*_*hHH 8

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

    yum install mod_proxy_html
Run Code Online (Sandbox Code Playgroud)
  1. 加载 mod_proxy_html 模块

    LoadModule proxy_html_module modules/mod_proxy_html.so
    
    Run Code Online (Sandbox Code Playgroud)
  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>  
    
    Run Code Online (Sandbox Code Playgroud)

希望这有帮助。