Frage Wie entferne ich den Pfad mit einem nginx proxy_pass


Ich habe eine laufende Web-Anwendung bei http://example.com/und möchte eine andere Anwendung auf einem separaten Server "mounten" http://example.com/en. Upstream-Server und proxy_pass scheinen zu funktionieren, aber für ein Problem:

upstream luscious {
 server lixxxx.members.linode.com:9001;
}

server {
  root /var/www/example.com/current/public/;
  server_name example.com;

  location /en {
    proxy_pass http://luscious;
  }
}

Beim Öffnen example.com/en, meine vorgelagerte Anwendung kehrt zurück 404 not found /en. Dies ist sinnvoll, da der Upstream den Pfad nicht hat /en.

Ist proxy_path die richtige Lösung? Sollte ich "upstream" umschreiben, so hört es zu /en stattdessen als Root-Pfad? Oder gibt es eine Direktive, die es mir erlaubt, den Pfad zu upstream neu zu schreiben?


47
2017-12-20 15:17


Ursprung




Antworten:


Dies ist wahrscheinlich der effizienteste Weg, um zu tun, was Sie wollen, ohne die Verwendung von regulären Ausdrücken:

location = /en {
    return 302 /en/;
}
location /en/ {
    proxy_pass http://luscious/;  # note the trailing slash here, it matters!
}

92
2017-12-21 03:09



Soweit ich weiß, würde der letzte Teil immer noch "/ en" als Weg zum Proxy weitergeben, nicht? - berkes
@berkes, nein, wird es nicht - der Schrägstrich in proxy_pass Was macht den Unterschied? Auch diese Antwort ist korrekter als die, die Sie gefunden haben, denn das sorgt auch dafür proxy_redirect bleibt bei defaultalso, du könntest es noch benutzen 302 et al in Ihrem Backend, und es funktioniert überall richtig. - cnst
Ah, mir fehlte der Schrägstrich :( - Vanuan
AAARGH! SCHRÄGSTRICH ! - barrymac
3 Stunden Suche, und ja ... Es war der Schrägstrich. Danke Kumpel! - Lucas P.


Ich möchte auf eine neuere Regex-basierte Antwort eingehen, die immer beliebter wird.

location ~ ^/en(/?)(.*)$ {  # OOPS!
  proxy_pass http://luscious/$2$is_args$args;  # OOPS!
}

Die Lösung mag auf den ersten Blick süßer erscheinen, aber aus mehreren Gründen ist sie falsch.

  • Der obige Regex würde einer Anfrage von uri entsprechen /enjoy, um es zu umleiten /joy stromaufwärts. Ist das wirklich beabsichtigt?

  • Eine Anfrage für /en führt nicht zu Weiterleitungen, die direkt eine / von der Upstream (fast als ob eine Anfrage für /en/ wurde stattdessen gemacht, aber nicht ganz). Wenn Sie relative URIs innerhalb Ihrer Root-Seite in der Upstream-Umgebung verwenden (sonst hätten Sie die /en/ Präfix direkt dort innerhalb der Upstream-URIs?), z.B. src="style.css" (die auf eine sprachspezifische verweisen kann url("menu.png")zum Beispiel), dann wird der Browser das als anfordern /style.css anstatt /en/style.css. (Oder sogar, wenn Sie absolute URIs überall verwenden, was ist, wenn jemand eine obskure halb-optionale Ressource relativ referenziert?) Hoppla, die Site funktioniert plötzlich nicht mehr, aber nur manchmal oder in Randfällen.

  • Nach meinem früherer Rat zu einer anderen Frage, die bereits in der eigenen Antwort des OP erwähnt wurdeMit regulären Ausdrücken wird das verhindert proxy_redirect Direktive mit dem Standardwert von default, drehe es runter auf off stattdessen. Dies bedeutet, dass wenn der Upstream mit antwortet Location: http://127.0.0.1:8080/en/dir/ wenn eine Anfrage für /en/dir gemacht, dann sieht der Klient das, was offensichtlich nicht richtig funktioniert. (Was wäre besonders ironisch gewesen für eine /en Englisch: www.doc-o-matic.com/webhelp/TdlgEditEdit.html Die Anfrage, die die Regex - Anwendung an erster Stelle auffordert, leidet jedoch an dieser spezifischen Implementierung, wie bereits oben erwähnt upstream Anweisung, dann könnte es besonders hässlich werden, wenn Sie nur versuchen, mit einer benutzerdefinierten zu gehen, besonders wenn Sie mehr als einen Upstream-Server haben - wie haben Sie eine separate proxy_redirect für jeden von denen? Sie können darin reguläre Ausdrücke verwenden proxy_redirectauch, vielleicht sogar um einen beliebigen Host zu finden, aber was ist, wenn Sie sich entscheiden, in Zukunft eine domainübergreifende Weiterleitung zu geben?

Um zu versuchen, einige der oben genannten Punkte mit einem einzigen Regex-basierten Ort zu behandeln, könnten wir Folgendes tun (beachten Sie, dass in proxy_pass wir mussten auch den Verweis auf einen Server von einem löschen upstreamRichtlinie zu machen proxy_redirect direkter):

location ~ ^/en/?((?<=/).*)?$ {
  location = /en { return 302 /en/; }
  proxy_pass http://127.0.0.1:8080/$1$is_args$args;
  proxy_redirect http://127.0.0.1:8080/ /en/;
}

Also, wenn Sie mich fragen, der ursprüngliche Lösung mit den zwei Geschwister-Top-Level-Standorten wäre immer noch eine bessere Idee, als sich in ein Kaninchenloch zu graben, indem man stattdessen die Regex-Route geht.


11
2017-10-14 04:51



Dies verursacht eine Ausnahme: nginx: [emerg] location "/en" is outside location "^/en/?((?<=/).* - Athlan
@Athlan, das ist, weil du das eigentlich nicht wirklich benutzen solltest! Wenn Sie das immer noch möchten, können Sie diesen Speicherort außerhalb des regulären Ausdrucks platzieren. - cnst
putting localation = / en outside funktioniert wirklich gut! Vielen Dank - Sebastian Webber


Also habe ich das gefunden antworte auf stackoverflow:

upstream luscious {
 server lixxxx.members.linode.com:9001;
}

server {
  root /var/www/example.com/current/public/;
  server_name example.com;

  location ~ ^/en(/?)(.*) {
    proxy_pass http://luscious/$2;
  }
}

Grundsätzlich: Übergeben einer Regex an einen Ort und Weiterleiten der Backref an die URL proxy_pass.


6
2017-12-20 15:30



Ich denke "proxy_pass üppig / $; sollte "proxy_pass" sein Luscious / $ 2" - Zafer
@Zafer hat Recht, die obige Antwort gab mir einen Fehler - franck
Ich habe die Antwort geändert, aber keinen Server zur Hand, wo ich dies versuchen kann, ATM, also ist es nicht verifiziert. - berkes