2017-10-27 5 views
0

Ich verwende nginx als Reverse-Proxy für einen Dienst, der auf Port 8080 des lokalen Computers ausgeführt wird. Zusätzlich muss ich Pfade, die mit/vp an den Upstream gesendet werden, voranstellen. Das ist einfach und ich habe einen Arbeits location Block für sie:Problem beim Umschreiben von URLs

location ~ ^/(.*?)$ { 
    proxy_pass $scheme://127.0.0.1:8080/vp/$1; 
    proxy_set_header Host $host; 
    proxy_redirect $scheme://$host/vp/ $scheme://$host/; 
} 

So würde das oben eine URL wie example.com/resource unterstützen und perfekt funktionieren.

Allerdings möchte ich auch URLs wie example.com/vp/resource unterstützen. Dazu muss ich einen anderen location Block schreiben, sonst würde es an den Upstream als /vp/vp/resource übergeben, was nicht funktioniert.

location ~ ^/vp/(.*?)$ { 
    rewrite /vp(.*?)$ /$1; 
} 

Die oben genannten Arbeiten, und ich habe jetzt Unterstützung für Urls wie example.com/vp/resource.

Aber ich habe eine letzte Sache, die ich gerne beheben würde. Wenn ein Benutzer auf example.com/vp/resource zugreifen möchte, soll die URL im Browser nur in example.com/resource umgeschrieben werden. Meine obige Konfiguration tut das nicht und ich weiß nicht, wie ich sie modifizieren soll. Ich dachte, der Punkt des Neuschreibens wäre, URLs im Browser zu schreiben, aber das scheint nicht der Fall zu sein.

Antwort

0

Zuerst habe ich versucht, dies ändern:

location ~ ^/vp/(.*?)$ { 
    rewrite /vp(.*?)$ /$1; 
} 

dazu:

location ~ ^/vp/(.*?)$ { 
    return /$1; 
} 

Und dies funktioniert meistens. Alle URIs, die mit/vp beginnen, werden auf solche umgeleitet, ohne die URL im Browser zu ändern. Dies hatte jedoch den Nebeneffekt, dass POST-Anfragen nicht funktionieren. Dies liegt daran, dass die POST-Anforderung den Upstream-Server nie erreicht. Stattdessen gibt der POST die 301-Weiterleitung sofort zurück, ohne einen Proxy-Pass. Der Browser erhält dann den Umleitungsstandort und das ist das Ende.

Also ich musste selektiv eine echte 301 nur zurückgeben, wenn die Anfrage kein POST war und wenn es war ich brauchte proxy_pass es. Nach dem Lesen der If is Evil habe ich gelernt, dass ich eine proxy_pass innerhalb einer if (innerhalb einer location), nur return und rewrite nicht verwenden kann. Beim Lesen auf rewrite erfuhr ich, dass es den URI einer Anfrage neu schreibt, aber nicht sofort an den Client zurücksendet. Stattdessen führt es den neu geschriebenen URI gegen alle location Blöcke aus und führt die Übereinstimmung aus. Also in meinem Fall musste ich nur einen rewrite verwenden, um meinen ursprünglichen location Block auszuführen.

Meine letzte Config endete wie folgt aussehen:

location ~ ^/vp/(.*?)$ { 
    if ($request_method = POST) { 
     rewrite /vp(.*?)$ /$1; 
    } 

    if ($request_method != POST) { 
     return 301 /$1; 
    } 
} 

location ~ ^/(.*?)$ { 
    proxy_pass http://127.0.0.1:8080/vp/$1; 
    proxy_set_header Host $host; 
    proxy_redirect $scheme://$host/vp/ $scheme://$host/; 
}