Como lidar com URLs relativos corretamente com um proxy reverso

51

Eu tenho uma configuração de proxy reverso da seguinte maneira no Apache:

O servidor A com o endereço www.example.com/folder é o servidor proxy reverso.

Ele mapeia para: Servidor B com endereço test.madeupurl.com

Este tipo de obras. Mas o problema que tenho é que, em www.example.com/folder, todos os links relativos são dos formatos www.example.com/css/examplefilename.css, em vez de www.example.com/folder/css/examplefilename. css

Como faço para corrigir isso?

Até agora, meu proxy reverso possui isso no servidor A (www.example.com):

<Location /folder>
    ProxyPass  http://test.madeupurl.com
    ProxyPassReverse http://test.madeupurl.com
</Location>
Trabalhador
fonte
Qual das soluções abaixo funcionou para você na resposta de HBruijn, se você se lembra?
Kimberly W

Respostas:

81

O Apache ProxyPassRewrite não reescreve os corpos de resposta recebidos de http://test.example.com , apenas cabeçalhos (como redirecionamentos para uma página 404 e outras).

Várias alternativas:

Um ) Reescreva o aplicativo interno para usar caminhos relativos em vez de absolutos. ou seja, em ../css/style.cssvez de/css/style.css

Dois ) Reimplemente o aplicativo interno no mesmo subdiretório, /foldere não na raiz de test.example.com.

Três ) É improvável que um e dois aconteçam ... Se você tiver sorte, o aplicativo interno usa apenas dois ou três subdiretórios e esses não são utilizados no site principal , basta escrever várias linhas de 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/

Quatro ) Crie um subdomínio separado para o aplicativo interno e simplesmente inverta o proxy:

<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>

Cinco ) Às vezes, os desenvolvedores são completamente à nora e têm as suas aplicações não só gerar absoluta URL de mas mesmo incluir a parte hostname em sua URL do e as resultantes olhares de código HTML como este: <img src=http://test.example.com/icons/logo.png>.

A ) Você pode usar a solução combinada de um DNS com horizonte dividido e o cenário 4. Os usuários internos e externos usam o test.example.com, mas o DNS interno aponta diretamente para o endereço IP do servidor test.example.com. Para usuários externos, o registro público de test.example.com aponta para o endereço IP do seu servidor público em www.example.com e você pode usar a solução 4.

B ) Na verdade, você pode obter do apache não apenas solicitações de proxy para test.example.com, mas também reescrever o corpo da resposta antes que ele seja transmitido aos seus usuários. (Normalmente, um proxy apenas reescreve os cabeçalhos / respostas HTTP). mod_substitute no apache 2.2. Não testei se ele se comporta bem com mod_proxy, mas talvez o seguinte funcione:

<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>
HBruijn
fonte
4
Boa vaca boa resposta. Ainda nem tentei nada disso, mas só queria agradecer pelo artigo! Ajuda um milhão. Vai testar algumas dessas idéias agora e informará em breve :) #
Hard worker
Pergunta rápida, por favor, para o ponto 2, se entendi corretamente, senhor, você está sugerindo que eu reimplemente o adpp em test.madeupurl.com/folder? Isso exigiria alterações no meu arquivo de configuração do apache? Isto parece a solução mais rápida #
Hard worker
Além disso, lamento incomodá-lo, mas com o ponto 1, quando tento o que você sugere, o problema que descrevo em minha pergunta ainda persiste. Por exemplo, aqui eu usei: <link rel = "stylesheet" type = "text / css" href = "../ css / custom.css" /> e para o endereço do link no navegador, ele está exibindo test.madeupurl.com /css/bootstrap.css em vez de test.madeupurl.com/folder/css/bootstrap.css . Gostaria de ter alguma sugestão sobre isso, seria muito útil #
21713 Trabalhador
Muitas vezes, quando você redistribuir um aplicativo que já está instalado no DocumentRoot para um subdiretório como / pasta as folhas de estilo, ícones etc será implantado em / pasta / css e / pasta / ícones etc. Então links na saída HTML será como <img src=/folder/icons/button.png>que por a vez será capturada pela ProxyPass /folder/ http://test.madeupurl.com/folder/diretiva.
HBruijn
A página test.madeupurl.com/content/index.html deseja incluir test.madeupurl.com/css/custom.css. Nesse local, você deve usar o URL relativo href="../css/custom.css"e não href="/css/custom.css". Quando o usuário da Internet recuperar a página, o URL será www.example.com/folder/content/index.html. A URL para o css será então: www.example.com/folder/content/../css/custom.cssqual é realmente a www.example.com/folder/css/custom.cssqual será encaminhada test.madeupurl.com/css/custom.css.
precisa
8

Como complemento da resposta do HBruijn , se você optar pela solução (3) "ProxyPass", poderá ser necessário também usar o mod_proxy_html para reescrever alguns URLs nas suas páginas HTML.

cf. Como lidar com URLs relativos corretamente com um proxy reverso para alguns exemplos.

Como um exemplo aplicado, veja como você pode configurar o Apache usando a ProxyHTMLURLMapregra para encaminhar tudo em your-domain-name.com/pad para sua instância Etherpad em execução localmente na porta 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]

Lucas Cimon
fonte
2
Esteja ciente de que o mod_proxy_html está incluído apenas no Apache 2.4 e
versões posteriores
Sua resposta é impecável. No entanto, conheci um caso em que o conteúdo não é html, é bastante pdf. Usar o ProxyHTMLURLMap não funcionou para mim. Alguma outra sugestão?
Mohamed Ennahdi El Idrissi
2
Se o seu conteúdo é um PDF, você não precisa reescrever os URLs! A menos que você queira que seus usuários cliquem em links no PDF para acessar outras páginas do seu site, mas isso parece complicado. Para desativar a reescrita de URL, simplesmente omita as duas últimas diretivas: SetOutputFilter& ProxyHTMLURLMap.
Lucas Cimon
Pode ser necessário adicionar RequestHeader não definido como Accept-Encoding para evitar erros de codificação
zar3bski
5

Você pode usar a seguinte maneira de criar um proxy reverso:
1. Instale mod_proxy_html

    yum install mod_proxy_html
  1. Carregar o módulo mod_proxy_html

    LoadModule proxy_html_module modules/mod_proxy_html.so
    
  2. E use a seguinte configuração

    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>  
    

Espero que esta ajuda.

ThanhHH
fonte