Cómo manejar correctamente las URL relativas con un proxy inverso

51

Tengo una configuración de proxy inverso de la siguiente manera en Apache:

El servidor A con dirección www.example.com/folder es el servidor proxy inverso.

Se asigna a: Servidor B con dirección test.madeupurl.com

Este tipo de trabajos. Pero el problema que tengo es, en www.example.com/folder, todos los enlaces relativos son de los formularios www.example.com/css/examplefilename.css en lugar de www.example.com/folder/css/examplefilename. css

¿Cómo puedo solucionar esto?

Hasta ahora, mi proxy inverso tiene esto en el Servidor A (www.example.com):

<Location /folder>
    ProxyPass  http://test.madeupurl.com
    ProxyPassReverse http://test.madeupurl.com
</Location>
Gran trabajador
fuente
¿Cuál de las siguientes soluciones funcionó para usted en la respuesta de HBruijn, si lo recuerda?
Kimberly W

Respuestas:

81

Apache ProxyPassRewrite no reescribe los cuerpos de respuesta recibidos de http://test.example.com , solo encabezados (como redireccionamientos a una página 404 y tal).

Una serie de alternativas:

Uno ) Reescribe la aplicación interna para usar rutas relativas en lugar de absolutas. es decir, en ../css/style.csslugar de/css/style.css

Dos ) /folderVuelva a implementar la aplicación interna en el mismo subdirectorio en lugar de en la raíz de test.example.com.

Tres ) Es poco probable que sucedan uno y dos ... Si tiene suerte, la aplicación interna solo usa dos o tres subdirectorios y esos no se usan en su sitio principal , simplemente escriba un montón de líneas 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/

Cuatro ) Cree un subdominio separado para la aplicación interna y simplemente invierta todo el 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 ) A veces los desarrolladores son totalmente desorientado y tener sus aplicaciones no sólo generan absoluta URL pero incluso incluyen la parte de host en su URL y las miradas resultantes de código HTML como este: <img src=http://test.example.com/icons/logo.png>.

A ) Puede usar la solución combinada de un DNS de horizonte dividido y el escenario 4. Los usuarios internos y externos usan test.example.com, pero su DNS interno apunta directamente a la dirección IP del servidor test.example.com. Para usuarios externos, el registro público de test.example.com apunta a la dirección IP de su servidor web público www.example.com y luego puede usar la solución 4.

B ) En realidad, puede obtener apache no solo para las solicitudes de proxy para test.example.com, sino también para reescribir el cuerpo de la respuesta antes de que se transmita a sus usuarios. (Normalmente, un proxy solo reescribe encabezados / respuestas HTTP). mod_substitute en apache 2.2. No he probado si se apila bien con mod_proxy, pero tal vez lo siguiente 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
fuente
44
Santa vaca buena respuesta. ¡Ni siquiera he probado ninguno de estos pero solo quería decir gracias por el artículo! Ayuda un millón. Voy a probar algunas de estas ideas ahora e informaremos en breve :)
Trabajador duro
Pregunta rápida, por favor, para el punto 2, si le entiendo correctamente, señor, ¿está sugiriendo que vuelva a implementar el adpp en test.madeupurl.com/folder? ¿Esto requeriría algún cambio en mi archivo de configuración de Apache? Esta parece ser la solución más rápida
Trabajador duro
Además, lamento molestarlo, pero con el punto 1 cuando intento lo que sugiere, el problema que describo en mi pregunta aún persiste. Por ejemplo, aquí utilicé: <link rel = "stylesheet" type = "text / css" href = "../ css / custom.css" /> y para la dirección del enlace en el navegador está generando test.madeupurl.com /css/bootstrap.css en lugar de test.madeupurl.com/folder/css/bootstrap.css . ¿Te gustaría tener alguna sugerencia sobre esto? Sería de gran ayuda
Trabajador duro
A menudo, cuando vuelve a implementar una aplicación que ahora está instalada en DocumentRoot en un subdirectorio como / folder, las hojas de estilo, iconos, etc. se implementarán en / folder / css y / folder / icons, etc. Luego, los enlaces en la salida HTML se convertirán <img src=/folder/icons/button.png>en el turno será atrapado por la ProxyPass /folder/ http://test.madeupurl.com/folder/directiva.
HBruijn
La página test.madeupurl.com/content/index.html quiere incluir test.madeupurl.com/css/custom.css. En esa ubicación, debe usar la URL relativa href="../css/custom.css"y no href="/css/custom.css". Cuando el usuario de Internet recupere la página, la URL será www.example.com/folder/content/index.html. La URL para el CSS entonces será: www.example.com/folder/content/../css/custom.cssque en realidad es a la www.example.com/folder/css/custom.cssque se reenviará test.madeupurl.com/css/custom.css.
HBruijn
8

Como complemento a la respuesta de HBruijn , si opta por la solución (3) "ProxyPass", es posible que también deba usar mod_proxy_html para reescribir algunas URL en sus páginas HTML.

cf. Cómo manejar correctamente las URL relativas con un proxy inverso para algunos ejemplos.

Como ejemplo aplicado, así es cómo puede configurar Apache usando la ProxyHTMLURLMapregla para reenviar todo en your-domain-name.com/pad a su instancia de Etherpad que se ejecuta localmente en el puerto 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
fuente
2
Sin embargo, tenga en cuenta que mod_proxy_html solo se incluye desde Apache 2.4 y
versiones
Tu respuesta es impecable. Sin embargo, conocí un caso en el que el contenido no es html, es más bien pdf. Usar ProxyHTMLURLMap no funcionó para mí. ¿Cualquier otra sugerencia?
Mohamed Ennahdi El Idrissi
2
Si su contenido es un PDF, ¡no necesita reescribir las URL en él! A menos que desee que sus usuarios hagan clic en los enlaces en el PDF para acceder a otras páginas de su sitio web, pero esto suena complicado. Para deshabilitar la reescritura de URL, simplemente omita las 2 últimas directivas: SetOutputFilter& ProxyHTMLURLMap.
Lucas Cimon
Es posible que deba agregar RequestHeader sin configurar Accept-Encoding para evitar errores de codificación
zar3bski
5

Puede usar la siguiente forma para crear un proxy inverso:
1. Instale mod_proxy_html

    yum install mod_proxy_html
  1. Cargue el módulo mod_proxy_html

    LoadModule proxy_html_module modules/mod_proxy_html.so
    
  2. Y use la siguiente configuración

    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 esto ayude.

ThanhHH
fuente