Acontece que foi um bug no mod_proxy_html: link e link . Apliquei a alteração do código no primeiro link e o conteúdo em partes começou a funcionar corretamente.
Estou executando o Apache 2.2.15-29 no RHEL 6 (na verdade, o Scientific Linux 6.4) e estou tentando configurar um proxy reverso com reescrita de conteúdo para que todos os links nas páginas da Web com proxy sejam reescritos para fazer referência o host do proxy. Estou com um problema de reescrever o conteúdo e gostaria de saber se isso é um bug ou se estou fazendo algo errado (e como fazer certo, se aplicável).
Estou fazendo proxy de um subdiretório em um host interno ( internal.example.com/foo
) na raiz de um host externo ( external.example.com
). Preciso reescrever conteúdo HTML, CSS e Javascript para corrigir todos os URLs. Também estou hospedando alguns conteúdos localmente no host externo, o que não acho que seja um problema, mas estou mencionando aqui por completo.
Meu httpd.conf parece mais ou menos assim:
<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>
A reescrita text / html funciona muito bem. Quando uso mod_substitute ou mod_ext_filter, o servidor externo envia as páginas como Transfer-Encoding: chunked
, envia todos os dados e fecha a conexão sem enviar o bloco final de comprimento zero. Alguns clientes HTTP estão insatisfeitos com isso. (O Google Chrome não processará qualquer conteúdo enviado dessa maneira, por exemplo, para que as páginas não apliquem CSS a elas.)
Aqui está uma sessão wget de amostra:
$ 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.
Estou fazendo algo errado? Estou acertando algum tipo de bug do Apache? O que preciso fazer para que funcione? (Note que eu prefiro que as soluções que funcionam dentro dos RPMs empacotados no RHEL-6 e a atualização para o Apache 2.4 sejam o último recurso, já que temos muita infraestrutura construída em torno do 2.2 neste sistema no momento.)
Tags reverse-proxy apache-2.2