Frage Nginx Redirect über Proxy, Rewrite und Preserve URL


In Nginx haben wir versucht, eine URL wie folgt umzuleiten:

http://example.com/some/path -> http://192.168.1.24

wo der Benutzer immer noch die ursprüngliche URL in seinem Browser sieht. Sobald der Benutzer umgeleitet wurde, sagen Sie, dass er auf den Link zu klicken /section/index.htmlWir möchten, dass dies eine Anfrage stellt, die zur Weiterleitung führt

http://example.com/some/path/section/index.html -> http://192.168.1.24/section/index.html

und noch einmal die ursprüngliche URL beibehalten.

Unsere Versuche haben verschiedene Lösungen mit Proxies und Rewrite Regeln beinhaltet, und unten zeigt die Konfiguration, die uns am nächsten zu einer Lösung gebracht hat (beachten Sie, dass dies die Webserver Konfiguration für die example.com Webserver). Es gibt jedoch noch zwei Probleme damit:

  • Es führt das Umschreiben nicht korrekt durch, da die Anforderungs-URL vom Webserver empfangen wird http://192.168.1.24 beinhaltet /some/path und daher die angeforderte Seite nicht zu bedienen.
  • Wenn Sie den Mauszeiger über einen Link halten, sobald eine Seite geliefert wurde, /some/path fehlt in der URL

    server {
        listen          80;
        server_name     www.example.com;
    
        location /some/path/ {
            proxy_pass http://192.168.1.24;
            proxy_redirect http://www.example.com/some/path http://192.168.1.24;
            proxy_set_header Host $host;
        }
    
        location / {
            index index.html;
            root  /var/www/example.com/htdocs;
        }
    }
    

Wir suchen nach einer Lösung, die nur die Konfiguration des Webservers ändert example.com. Wir können die Konfiguration ändern 192.168.1.24 (auch Nginx), aber wir wollen versuchen, dies zu vermeiden, weil wir dieses Setup für hunderte von verschiedenen Servern wiederholen müssen, deren Zugriff durchprobiert wird example.com.


63
2018-04-04 00:49


Ursprung




Antworten:


Erstens sollten Sie nicht verwenden root Anweisung innerhalb des Standortblocks ist es eine schlechte Übung. In diesem Fall spielt es keine Rolle.

Versuchen Sie, einen zweiten Standortblock hinzuzufügen:

location ~ /some/path/(?<section>.+)/index.html {
    proxy_pass http://192.168.1.24/$section/index.html;
    proxy_set_header Host $host;
}

Dies fängt den Teil nach / some / path / und vor index.html in eine $ section-Variable ein, die dann verwendet wird, um das proxy_pass-Ziel zu setzen. Sie können die Regex bei Bedarf spezifischer gestalten.


54
2018-04-04 05:24



Entschuldigung für die späte Antwort - das ist so nahe daran, zu erreichen, wonach wir suchen. Der einzige Mangel besteht darin, dass die URLs für Links im Browser, nachdem die Zielseite geliefert wurde, "/ einige / Pfad /" nicht enthalten, was bedeutet, dass sie nicht funktionieren, wenn ein Benutzer darauf klickt. Wenn wir herausfinden können, wie wir das überwinden können, werde ich diese Antwort aktualisieren und akzeptieren, da sie so nah ist. - robjohncox
Die Links, die der Browser sieht, werden von der Software generiert, die auf dem Server 192.168.1.24 ausgeführt wird. Sie sollten diese Software ändern, um zu erreichen, was Sie wollen. - Tero Kilkanen
Ich bin mir nicht sicher, ob ich Ihrer Warnung über den Root-Standortblock folge. Lesen von Nginx-Dokumentation ist der richtige Weg, um Dinge zu tun. Sie warnen nur, dass es keine Standardwurzel außerhalb aller Standorte gibt. nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/... - guy mograbi
Nun, es ist einfacher, eine Faustregel nicht zu verwenden root in einem location blockieren, dann werden Sie kein unerwartetes Verhalten für Standardspeicherorte erhalten. Nur wenn Sie den Standard ändern müssen root für jeden Standort, dann können Sie es verwenden. - Tero Kilkanen
Was meinst du mit empfängt den $ host als Namen? Was ist der genaue HTTP-Header, der gesendet wurde und was genau er senden soll? - Tero Kilkanen


Sie sollten den URI-Part in verwenden proxy_pass Richtlinie. Außerdem haben Sie die Bestellargumente von verwechselt proxy_redirect Richtlinie, und wahrscheinlich brauchen Sie es überhaupt nicht. Nginx hat einen angemessenen Standardwert für diese Anweisung.

In diesem Fall location Block könnte wirklich einfach sein:

location /some/path/ {
    proxy_pass http://192.168.1.24/;
    # note this slash  -----------^
    proxy_set_header Host $host;
}

55
2018-04-04 06:17



Entschuldigung für die späte Antwort - ich habe es ausprobiert und leider funktioniert es nicht für unseren Anwendungsfall. Das Problem ist, dass, wenn die Anfrage auf dem Zielserver gemacht wird /some/path/ Ein Teil der URL bleibt in der Anfrage erhalten, die keine gültige URL ist (wir müssen die URL auch neu schreiben, um dies zu entfernen). - robjohncox
@robjohncox was genau hast du probiert? - Alexey Ten
der Schrägstrich hat den Trick für mich gemacht. Nun ist mydomain.com/some/path/* korrekt auf 192.168.1.24/* und nicht 192.168.1.24/some/path/* - Vadimo
Kann ich den Kommentar "# notieren Sie diesen Schrägstrich" in dieser Antwort aktualisieren? Dreifacher Beifall für diesen Kommentar! - 8one6
Nicht sicher, wie das für euch alle funktioniert. Das versuche ich zu erreichen. Wenn ein Benutzer jedoch auf einen Link klickt, der z. zu 192.168.1.24/login auf dem lokalen Dienst wird er zu mydomain.com/login statt mydomain.com/some/path/login umgeleitet - mueslo


Sie können die folgende Konfiguration verwenden, um eine 100% nahtlose Zuordnung zwischen beiden zu haben /some/path/ auf der Vorderseite und / auf dem Backend.

Beachten Sie, dass dies die einzige Antwort ist, die sich nahtlos um die Erzeugung von absoluten Pfaden kümmert 404 Not Found Fehler, vorausgesetzt, dass das richtige HTTP Referer Der Header wird vom Browser gesendet. Daher sollten alle diese Gifs weiterhin geladen werden, ohne dass der zugrunde liegende HTML-Code geändert werden muss (was nicht nur teuer ist, sondern auch ohne zusätzliche Module, die nicht standardmäßig kompiliert werden, nicht unterstützt wird).

location /some/path/ {
    proxy_pass http://192.168.1.24/; # note the trailing slash!
}
location / {
    error_page 404 = @404;
    return 404; # this would normally be `try_files` first
}
location @404 {
    add_header Vary Referer; # sadly, no effect on 404
    if ($http_referer ~ ://[^/]*(/some/path|/the/other)/) {
        return 302 $1$uri;
    }
    return 404 "Not Found\n";
}

Sie können finden das komplette Proof-of-Concept und minimal-lebensfähige Produkt innerhalb des https://github.com/cnst/StackOverflow.cnst.nginx.conf Repository.

Hier ist ein Testlauf, um zu bestätigen, dass alle Randfälle funktionieren:

curl -v -H 'Referer: http://example.su/some/path/page.html' localhost:6586/and/more.gif | & fgrep -e HTTP/ -e Referer -e Location
> GET /and/more.gif HTTP/1.1
> Referer: http://example.su/some/path/page.html
< HTTP/1.1 302 Moved Temporarily
< Location: http://localhost:6586/some/path/and/more.gif
< Vary: Referer

curl -v localhost:6586/and/more.gif | & fgrep -e HTTP/ -e Referer -e Location
> GET /and/more.gif HTTP/1.1
< HTTP/1.1 404 Not Found

curl -v localhost:6586/some/path/and/more.gif | & fgrep -e HTTP/ -e Referer -e Location -e uri
> GET /some/path/and/more.gif HTTP/1.1
< HTTP/1.1 200 OK
request_uri:    /and/more.gif

P.S. Wenn Sie viele verschiedene Pfade zum Zuordnen haben, anstatt einen Regex-Vergleich durchzuführen $http_referer innerhalb eines if innerhalb location @404Vielleicht möchten Sie das global-basierte verwenden map Richtlinie stattdessen.

Beachten Sie auch, dass die abschließenden Schrägstriche in den beiden proxy_pass, ebenso wie location es ist enthalten in, sind ziemlich wichtig nach einer verwandten Antwort.

Verweise:


2
2017-08-27 03:42





Wenn dieser Schrägstrich zu einem Nginx-Proxy-Jenkins hinzugefügt wird, wird der Fehler "Es scheint, dass Ihr Reverse-Proxy-Setup ist kaputt" angezeigt.

proxy_pass          http://localhost:8080/;

Remove this -----------------------------^

Es sollte lesen

proxy_pass          http://localhost:8080;

1
2018-05-04 15:44