Wie man relative URLs mit einem Reverse Proxy richtig behandelt


51

Ich habe ein Reverse-Proxy-Setup wie folgt in Apache:

Server A mit der Adresse www.example.com/folder ist der Reverse-Proxy-Server.

Es ordnet zu: Server B mit der Adresse test.madeupurl.com

Diese Art von Arbeiten. Aber das Problem, das ich habe, ist, dass auf www.example.com/folder alle relativen Links die Form www.example.com/css/examplefilename.css haben und nicht www.example.com/folder/css/examplefilename. CSS

Wie behebe ich das?

Bisher hat mein Reverse Proxy dies auf Server A (www.example.com):

<Location /folder>
    ProxyPass  http://test.madeupurl.com
    ProxyPassReverse http://test.madeupurl.com
</Location>

Welche der folgenden Lösungen hat bei HBruijns Antwort für Sie funktioniert, wenn Sie sich erinnern?
Kimberly W

Antworten:


81

Apache ProxyPassRewrite schreibt die von http://test.example.com empfangenen Antworttextkörper nicht um, sondern nur die Header (wie Weiterleitungen zu einer 404-Seite usw. ).

Eine Reihe von Alternativen:

Erstens : Schreiben Sie die interne App neu, um relative Pfade anstelle von absoluten Pfaden zu verwenden. dh ../css/style.cssstatt/css/style.css

Zwei ) Stellen Sie die interne App erneut in demselben Unterverzeichnis /folderund nicht im Stammverzeichnis von test.example.com bereit.

Drei ) Eins und zwei sind oft unwahrscheinlich ... Wenn Sie Glück haben, dass die interne App nur zwei oder drei Unterverzeichnisse verwendet und diese auf Ihrer Hauptseite nicht verwendet werden , schreiben Sie einfach ein paar ProxyPass-Zeilen:

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

Vier ) Erstellen Sie eine separate Subdomain für die interne App und kehren Sie einfach den Proxy um:

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

Fünf ) Manchmal Entwickler sind völlig ahnungslos und haben ihre Anwendungen nicht nur absolute URLs erzeugen , sondern auch den Hostnamen an ihre URLs enthalten und die resultierende HTML - Code sieht wie folgt aus : <img src=http://test.example.com/icons/logo.png>.

A ) Sie können eine kombinierte Lösung aus einem Split-Horizon-DNS und Szenario 4 verwenden. Sowohl interne als auch externe Benutzer verwenden test.example.com, aber Ihr interner DNS verweist direkt auf die IP-Adresse des Servers von test.example.com. Für externe Benutzer verweist der öffentliche Datensatz für test.example.com auf die IP-Adresse Ihres öffentlichen Webservers www.example.com, und Sie können dann Lösung 4 verwenden.

B ) Sie können Apache dazu bringen, nicht nur Proxy-Anforderungen an test.example.com zu senden, sondern auch den Antworttext neu zu schreiben, bevor er an Ihre Benutzer übertragen wird. (Normalerweise schreibt ein Proxy nur HTTP-Header / -Antworten um). mod_substitute in apache 2.2. Ich habe nicht getestet, ob es mit mod_proxy gut stapelt, aber vielleicht funktioniert Folgendes:

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

4
Heilige Kuh gute Antwort. Ich habe noch nicht einmal versucht, aber ich wollte mich nur für das Schreiben bedanken! Hilft einer Million. Werde jetzt einige dieser Ideen testen und in Kürze darüber berichten :)
Harter Arbeiter

Kurze Frage, bitte, für Punkt 2, wenn ich Sie richtig verstehe, schlagen Sie vor, dass ich die Adpp erneut auf test.madeupurl.com/folder? Müssen hierfür Änderungen an meiner Apache-Konfigurationsdatei vorgenommen werden? Dies scheint die schnellste Lösung zu sein
Harter Arbeiter

Außerdem tut es mir leid, Sie zu stören, aber Punkt 1, wenn ich versuche, was Sie vorschlagen, bleibt das Problem, das ich in meiner Frage beschreibe, bestehen. Zum Beispiel habe ich hier verwendet: <link rel = "stylesheet" type = "text / css" href = "../ css / custom.css" /> und für die Linkadresse im Browser wird test.madeupurl.com ausgegeben /css/bootstrap.css statt test.madeupurl.com/folder/css/bootstrap.css . Hätten Sie hierzu Vorschläge, wäre dies am hilfreichsten
Harter Arbeiter

Wenn Sie eine Anwendung, die jetzt im DocumentRoot installiert ist, in einem Unterverzeichnis wie / folder erneut bereitstellen, werden die Stylesheets, Symbole usw. häufig in / folder / css und / folder / icons usw. bereitgestellt. Dann werden die Links in der HTML-Ausgabe so, wie <img src=/folder/icons/button.png>in wiederum wird von der ProxyPass /folder/ http://test.madeupurl.com/folder/Richtlinie erfasst.
HBruijn

Die Seite test.madeupurl.com/content/index.html soll test.madeupurl.com/css/custom.css enthalten. An dieser Stelle sollten Sie die relative URL verwenden href="../css/custom.css"und nicht href="/css/custom.css". Wenn der Internetbenutzer die Seite abruft, lautet die URL www.example.com/folder/content/index.html. Die URL für das CSS www.example.com/folder/content/../css/custom.csslautet dann: welches ist eigentlich www.example.com/folder/css/custom.csswelches wird weitergeleitet test.madeupurl.com/css/custom.css.
HBruijn

8

Wenn Sie sich als Ergänzung zu HBruijns Antwort für Lösung (3) "ProxyPass" entscheiden, müssen Sie möglicherweise auch mod_proxy_html verwenden , um einige URLs in Ihren HTML-Seiten neu zu schreiben.

vgl. Wie man relative URLs mit einem Reverse-Proxy für einige Beispiele richtig behandelt .

Im Folgenden finden Sie ein Beispiel, wie Sie Apache mithilfe der ProxyHTMLURLMapRegel so konfigurieren können , dass alles, was Sie unter your-domain-name.com/pad angegeben haben, an Ihre Etherpad- Instanz weitergeleitet wird, die lokal auf Port 9001 ausgeführt wird:

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


2
Beachten Sie jedoch, dass mod_proxy_html nur in Apache 2.4 und höher enthalten ist. Die ursprüngliche Frage
bezieht

Ihre Antwort ist einwandfrei. Ich bin jedoch auf einen Fall gestoßen, in dem der Inhalt nicht HTML, sondern PDF ist. Die Verwendung von ProxyHTMLURLMap hat bei mir nicht funktioniert. Irgendwelche anderen Vorschläge?
Mohamed Ennahdi El Idrissi

2
Wenn es sich bei Ihrem Inhalt um ein PDF handelt, müssen Sie darin keine URLs umschreiben! Es sei denn, Sie möchten, dass Ihre Benutzer auf Links in der PDF-Datei klicken, um auf andere Seiten Ihrer Website zuzugreifen. Dies klingt jedoch schwierig. Um das Umschreiben von URLs zu deaktivieren, lassen Sie einfach die letzten beiden Anweisungen weg: SetOutputFilter& ProxyHTMLURLMap.
Lucas Cimon

Möglicherweise müssen Sie RequestHeader hinzufügen und Accept-Encoding deaktivieren , um Codierungsfehler zu vermeiden
zar3bski

5

Sie können einen Reverse-Proxy folgendermaßen
erstellen : 1. Installieren Sie mod_proxy_html

    yum install mod_proxy_html
  1. Laden Sie das Modul mod_proxy_html

    LoadModule proxy_html_module modules/mod_proxy_html.so
    
  2. Und verwenden Sie die folgenden Einstellungen

    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>  
    

Ich hoffe das hilft.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.