我在 RHEL 6(实际上是 Scientific Linux 6.4)上运行 Apache 2.2.15-29,并尝试设置具有内容重写的反向代理,以便代理网页上的所有链接都重写以引用代理主机。我在部分内容重写方面遇到了问题,我想知道这是错误还是我做错了什么(以及如何正确执行,如果适用)。
我将内部主机 ( internal.example.com/foo
) 上的子目录代理到外部主机 ( ) 的根目录external.example.com
。我需要重写 HTML、CSS 和 Javascript 内容来修复所有 URL。我还在外部主机上本地托管了一些内容,我认为这不是问题,但是为了完整性我在这里提到了这一点。
我的 httpd.conf 大致如下:
<VirtualHost *:80>
ServerName external.example.com
ServerAlias example.com
# Serve all local content directly, reverse-proxy all unknown URIs.
RewriteEngine On
RewriteRule ^(/(index.html?)?)?$ http://internal.example.com/foo/ [P]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [L]
RewriteRule ^/~ - [L]
RewriteRule ^(.*)$ http://internal.example.com$1 [P]
# Standard header rewriting.
ProxyPassReverse / http://internal.example.com/foo/
ProxyPassReverseCookieDomain internal.example.com external.example.com
ProxyPassReverseCookiePath /foo/ /
# Strip any Accept-Encoding: headers from the client so we can process the pages
# as plain text.
RequestHeader unset Accept-Encoding
# Use mod_proxy_html to fix URLs in text/html content.
ProxyHTMLEnable On
ProxyHTMLURLMap http://internal.example.com/foo/ /
ProxyHTMLURLMap http://internal.example.com/foo /
ProxyHTMLURLMap /foo/ /
## Use mod_substitute to fix URLs in CSS and Javascript
#<Location />
# AddOutputFilterByType SUBSTITUTE text/css
# AddOutputFilterByType SUBSTITUTE text/javascript
# Substitute "s|http://internal.example.com/foo/|/|nq"
#</Location>
# Use mod_ext_filter to fix URLs in CSS and Javascript
ExtFilterDefine fixurlcss mode=output intype=text/css cmd="/bin/sed -rf /etc/httpd/fixurls"
ExtFilterDefine fixurljs mode=output intype=text/javascript cmd="/bin/sed -rf /etc/httpd/fixurls"
<Location />
SetOutputFilter fixurlcss;fixurljs
</Location>
</VirtualHost>
text/html 重写工作正常。当我使用 mod_substitute 或 mod_ext_filter 时,外部服务器会将页面发送为Transfer-Encoding: chunked
,发送所有数据,然后关闭连接而不发送最后的零长度块。一些 HTTP 客户端对此不满意。(例如,Chrome 不会处理以这种方式发送的任何内容,因此页面不会应用 CSS。)
以下是 wget 会话的示例:
$ wget -O /dev/null -S http://external.example.com/include/jquery.js
--2013-11-01 11:36:36-- http://external.example.com/include/jquery.js
Resolving external.example.com (external.example.com)... 192.168.0.1
Connecting to external.example.com (external.example.com)|192.168.0.1|:80... connected.
HTTP request sent, awaiting response...
HTTP/1.1 200 OK
Date: Fri, 01 Nov 2013 15:36:36 GMT
Server: Apache
Last-Modified: Tue, 29 Oct 2013 13:09:10 GMT
ETag: "1d60026-187b8-4e9e0ec273e35"
Accept-Ranges: bytes
Vary: Accept-Encoding
X-UA-Compatible: IE=edge,chrome=1
Content-Type: text/javascript;charset=utf-8
Connection: close
Transfer-Encoding: chunked
Length: unspecified [text/javascript]
Saving to: `/dev/null'
[ <=> ] 100,280 --.-K/s in 0.005s
2013-11-01 11:36:37 (19.8 MB/s) - Read error at byte 100280 (Success).Retrying.
--2013-11-01 11:36:38-- (try: 2) http://external.example.com/include/jquery.js
Connecting to external.example.com (external.example.com)|192.168.0.1|:80... connected.
HTTP request sent, awaiting response...
HTTP/1.1 416 Requested Range Not Satisfiable
Date: Fri, 01 Nov 2013 15:36:38 GMT
Server: Apache
Vary: Accept-Encoding
Content-Type: text/html;charset=utf-8
Content-Length: 260
Connection: close
The file is already fully retrieved; nothing to do.
我做错了什么吗?我是不是遇到了某种 Apache 错误?我需要做什么才能让它正常工作?(请注意,我更喜欢在 RHEL-6 打包的 RPM 中工作的解决方案,升级到 Apache 2.4 是最后的手段,因为目前我们在这个系统上有很多围绕 2.2 构建的基础设施。)
答案1
事实证明,这是 mod_proxy_html 中的一个错误:https://www.apachelounge.com/viewtopic.php?t=3552和http://marc.info/?l=apache-httpd-users&m=127237168923132&w=2。我在第一个链接中应用了代码更改,分块内容开始正常工作。