Comment gérer correctement les URL avec un proxy inverse

51

J'ai une configuration de proxy inverse comme suit dans Apache:

Le serveur A dont l'adresse www.example.com/folder est le serveur proxy inverse.

Il mappe vers: le serveur B avec l'adresse test.madeupurl.com

Ce genre de travaux. Mais le problème que j'ai est que, sur www.example.com/folder, tous les liens relatifs sont de la forme www.example.com/css/examplefilename.css plutôt que de www.example.com/folder/css/examplefilename. css

Comment puis-je réparer ça?

Jusqu'ici mon proxy inverse a ceci sur le serveur A (www.example.com):

<Location /folder>
    ProxyPass  http://test.madeupurl.com
    ProxyPassReverse http://test.madeupurl.com
</Location>
Bosseur
la source
Laquelle des solutions ci-dessous a fonctionné pour vous dans la réponse de HBruijn, si vous vous en souvenez?
Kimberly W

Réponses:

81

Apache ProxyPassRewrite ne réécrit pas les corps de réponse reçus de http://test.example.com , uniquement les en-têtes (comme les redirections vers une page 404, etc.).

Un certain nombre d'alternatives:

Un ) Réécrire l'application interne pour utiliser des chemins relatifs au lieu de absolus. c'est ../css/style.cssà dire au lieu de/css/style.css

Deux ) Redéployez l'application interne dans le même sous-répertoire /folderplutôt que dans la racine de test.example.com.

Trois ) Un et deux sont souvent improbables… Si vous avez de la chance, l'application interne utilise uniquement deux ou trois sous - répertoires et ceux qui ne sont pas utilisés sur votre site principal , écrivez simplement un tas de lignes 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/

Quatre ) Créez un sous-domaine distinct pour l'application interne et inversez simplement le 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>

Cinq ) Parfois , les développeurs sont complètement désemparés et leurs applications génèrent non seulement URL absolue de même , mais comprennent la partie de nom d' hôte dans leur apparence et de le code HTML résultant URL comme ceci: <img src=http://test.example.com/icons/logo.png>.

A ) Vous pouvez utiliser la solution combinée d'un DNS fractionné Horizon et du scénario 4. Les utilisateurs internes et externes utilisent le test.example.com, mais votre DNS interne pointe directement sur l'adresse IP du serveur de test.example.com. Pour les utilisateurs externes, l'enregistrement public de test.example.com pointe sur l'adresse IP de votre serveur Web public www.example.com. Vous pourrez ensuite utiliser la solution 4.

B ) Vous pouvez réellement obtenir Apache pour non seulement des demandes de proxy à test.example.com, mais également pour réécrire le corps de la réponse avant qu'elle ne soit transmise à vos utilisateurs. (Normalement, un proxy ne réécrit que les en-têtes / réponses HTTP). mod_substitute in apache 2.2. Je n'ai pas testé si cela fonctionne bien avec mod_proxy, mais peut-être que ça marche:

<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
la source
4
Sainte vache bonne réponse. Je n'ai même jamais essayé aucun de ceux-ci, mais je voulais juste dire merci pour la rédaction! Aide un million. Nous allons tester certaines de ces idées maintenant et nous vous en informerons bientôt :)
Travailleur
Question rapide, s'il vous plaît, pour le point 2, si je vous ai bien compris, vous suggérez que je redéploie adpp en test.madeupurl.com/folder? Cela nécessiterait-il des modifications dans mon fichier de configuration Apache? Cela ressemble à la solution la plus rapide
Travailleur
En outre, désolé de vous déranger, mais avec le point 1 lorsque j'essaie ce que vous suggérez, le problème que je décris dans ma question persiste. Par exemple ici, j’ai utilisé: <link rel = "stylesheet" type = "text / css" href = "../ css / custom.css" /> et pour l’adresse du lien dans le navigateur, elle est testting test.madeupurl.com /css/bootstrap.css plutôt que test.madeupurl.com/folder/css/bootstrap.css . Auriez-vous des suggestions à ce sujet, il serait très utile
Travailleur
Souvent , lorsque vous redéployer une application qui est maintenant installé dans le DocumentRoot à un sous - répertoire comme / dossier les feuilles de style, icônes etc seront déployés dans / dossier / css et / dossier / icônes , etc. Ensuite , des liens dans la sortie HTML deviendront comme <img src=/folder/icons/button.png>qui tour sera capturé par la ProxyPass /folder/ http://test.madeupurl.com/folder/directive.
HBruijn
La page test.madeupurl.com/content/index.html veut inclure test.madeupurl.com/css/custom.css. À cet endroit, vous devez utiliser l'URL relative href="../css/custom.css"et non href="/css/custom.css". Lorsque l'internaute récupère la page, l'URL est www.example.com/folder/content/index.html. L'URL pour le css sera alors: www.example.com/folder/content/../css/custom.cssqui est en fait celui www.example.com/folder/css/custom.cssqui sera transféré à test.madeupurl.com/css/custom.css.
HBruijn
8

En complément de la réponse de HBruijn , si vous optez pour "ProxyPass" de solution (3) , vous devrez peut-être également utiliser mod_proxy_html pour réécrire certaines URL dans vos pages HTML.

cf. Comment gérer correctement les URL avec un proxy inverse pour certains exemples.

À titre d'exemple, voici comment vous pouvez configurer Apache en utilisant la ProxyHTMLURLMaprègle pour tout transférer sur votre-nom-de-domaine.com/pad vers votre instance Etherpad s'exécutant localement sur le port 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
la source
2
Sachez cependant que mod_proxy_html est uniquement inclus à partir d'Apache 2.4, et que la question ci-dessus est pour Apache 2.2
HBruijn 10/10
Votre réponse est impeccable. Cependant, j'ai rencontré un cas où le contenu n'est pas html, c'est plutôt pdf. Utiliser ProxyHTMLURLMap n'a pas fonctionné pour moi. D'autres suggestions?
Mohamed Ennahdi El Idrissi
2
Si votre contenu est au format PDF, vous n'avez pas besoin de réécrire les URL! Sauf si vous souhaitez que vos utilisateurs cliquent sur des liens dans le fichier PDF pour accéder à d'autres pages de votre site Web, cela semble compliqué. Pour désactiver la réécriture d'URL, omettez simplement les 2 dernières directives: SetOutputFilter& ProxyHTMLURLMap.
Lucas Cimon
Vous aurez peut-être besoin d'ajouter RequestHeader unset pour accepter l'encodage afin d'éviter les erreurs d'encodage
zar3bski
5

Vous pouvez utiliser la méthode suivante pour créer un proxy inverse:
1. Installez mod_proxy_html.

    yum install mod_proxy_html
  1. Charger le module mod_proxy_html

    LoadModule proxy_html_module modules/mod_proxy_html.so
    
  2. Et utiliser le réglage suivant

    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>  
    

J'espère que cette aide.

ThanhHH
la source