Deaktivieren der URL-Dekodierung im Nginx-Proxy


21

Wenn ich zu dieser URL navigiere, empfängt http://localhost:8080/foo/%5B-%5Dserver ( nc -l 8080) sie wie sie ist:

GET /foo/%5B-%5D HTTP/1.1

Wenn ich diese Anwendung jedoch über Nginx (1.1.19) als Proxy verwende:

location /foo {
        proxy_pass    http://localhost:8080/foo;
}

Dieselbe Anfrage, die über den Nginx-Port weitergeleitet wird, wird mit dekodiertem Pfad weitergeleitet:

GET /foo/[-] HTTP/1.1

Dekodierte eckige Klammern im GET-Pfad verursachen die Fehler auf dem Zielserver ( HTTP-Status 400 - Unzulässiges Zeichen im Pfad ... ), wenn sie ohne Escapezeichen eintreffen.

Gibt es eine Möglichkeit, die URL-Dekodierung zu deaktivieren oder zurück zu kodieren, damit der Zielserver bei der Weiterleitung durch nginx genau denselben Pfad erhält? Eine clevere Regel zum Umschreiben von URLs?


Fehler an nginx gemeldet
— Tomasz Nurkiewicz

Antworten:


19

Zitat Valentin V. Bartenev (wer sollte die volle Anerkennung für diese Antwort bekommen):

Ein Zitat aus der Dokumentation :

  • Wenn mit URI proxy_pass angegeben wird , wird beim Übergeben einer Anforderung an den Server ein Teil einer normalisierten Anforderungs-URI, die mit dem Speicherort übereinstimmt, durch eine in der Direktive angegebene URI ersetzt

  • Wenn proxy_passangegeben wird , ohne URI , wird eine Anforderung URI an den Server in der gleichen Form übergeben , wie durch einen Client gesendet wird, wenn eine ursprüngliche Anfrage ist

Die richtige Konfiguration in Ihrem Fall wäre:

location /foo {
   proxy_pass http://localhost:8080;
}

8
Ich musste umsteigen http://localhost:8080/, http://localhost:8080falls jemand die gleiche Situation hat wie ich.
— Herrtim

4
Warum dekodiert Nginx den URI, bevor er an den Back-End-Server übergeben wird? Wäre es nicht sinnvoller, die URI unangetastet zu lassen?
— Schnabeltier

@platypus, es bleibt unangetastet, bis Sie explizit beginnen, die Substitutionen
— durchzuführen

2

Beachten Sie, dass die URL-Dekodierung, die in der Dokumentation von nginx allgemein als $uri"Normalisierung" bezeichnet wird , vor dem Back-End-IFF erfolgt:

  • Entweder wird ein beliebiger URI in sich proxy_passselbst angegeben, auch wenn nur der abschließende Schrägstrich für sich allein steht.

  • oder URI wird während der Verarbeitung geändert, z rewrite. B. durch .


Beide Bedingungen sind explizit unter http://nginx.org/r/proxy_pass (Hervorhebung meiner) dokumentiert :

  • Wenn die proxy_passDirektive mit einem URI angegeben wird, wird der Teil einer normalisierten Anforderungs-URI, der mit dem Speicherort übereinstimmt, durch einen in der Direktive angegebenen URI ersetzt , wenn eine Anforderung an den Server übergeben wird

  • Wenn proxy_passangegeben wird , ohne einen URI , wird die Anforderung URI an den Server in der übergebenen gleichen Form wie die von einem Client gesendet , wenn die ursprüngliche Anforderung verarbeitet wird, oder die gesamte normierte Anforderung URI übergeben wird , wenn die Verarbeitung geändert URI


Die Lösung besteht darin, entweder die URI wegzulassen, wie im Fall von OPs, oder in der Tat eine clevere rewriteRegel zu verwenden:

# map `/foo` to `/foo`:
location /foo {
    proxy_pass  http://localhost:8080;  # no URI -- not even just a slash
}

# map `/foo` to `/bar`:
location /foo {
    rewrite  ^  $request_uri;            # get original URI
    rewrite  ^/foo(/.*)  /bar$1  break;  # drop /foo, put /bar
    return 400;   # if the second rewrite won't match
    proxy_pass    http://localhost:8080$uri;
}

Sie können es live in einer verwandten Stapelüberlauf-Antwort sehen , einschließlich der Kontrollgruppe.


Die Dokumentation ist hier verwirrend. Beide Formulare enthalten eine URI. Es ist die Pfadkomponente , die in der einen vorhanden ist und in der anderen fehlt.
— Michael Hampton

@MichaelHampton, da bin ich anderer Meinung. Der Pfad wird im Allgemeinen als URI bezeichnet. Der Pfad ohne URI enthält also keine URI.
— cnst

Ein relativer Pfad allein kann natürlich auch eine gültige URL sein. Der Punkt ist, der Rest ist auch eine gültige URI (zB http://localhost:8080). Wenn Sie anderer Meinung sind, können Sie sich an die Autoren von RFC 3986 wenden.
— Michael Hampton

@MichaelHampton Leider scheint es, Schema und Pfad sind obligatorisch, um eine URI zu sein, Autorität, Argumente, Fragment sind optional
— Norman Xu
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.