Vraag Hoe het pad te verwijderen met een nginx proxy_pass


Ik heb een lopende web-applicatie bij http://example.com/en u wilt een andere toepassing "mounten" op een afzonderlijke server http://example.com/en. Upstream-servers en proxy_pass lijken te werken, maar voor één probleem:

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

Bij opening example.com/en, mijn upstream-applicatie retourneert 404 not found /en. Dit is logisch, omdat de stroomopwaarts niet het pad heeft /en.

is proxy_path de juiste oplossing? Moet ik "stroomopwaarts" herschrijven, zodat het luistert /en in plaats daarvan, als het root-pad? Of is er een richtlijn die me in staat stelt om het pad dat stroomopwaarts stroomt te herschrijven?


47
2017-12-20 15:17


oorsprong




antwoorden:


Dit is waarschijnlijk de meest efficiënte manier om te doen wat u wilt, zonder het gebruik van reguliere expressies:

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

92
2017-12-21 03:09



Voor zover ik weet, zou het laatste deel nog steeds "/ en" als pad doorgeven aan de proxy, niet? - berkes
@berkes, nee, dat zal niet gebeuren - de trash schuine streep in proxy_pass is wat een verschil maakt. Ook is dit antwoord correcter dan dat je bedacht hebt, want het zorgt er ook voor dat proxy_redirect blijft bij default, dus je zou nog steeds kunnen gebruiken 302 et al in je backend, en laat het overal goed werken. - cnst
Ah, ik miste de achterblijvende slash :( - Vanuan
AAARGH! TRAILING SLASH! - barrymac
3 uur zoeken en ja ... Het was de trash. Bedankt vriend! - Lucas P.


Ik zou graag een nieuw, op regex gebaseerd antwoord willen aanpakken dat steeds populairder wordt.

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

De oplossing lijkt op het eerste gezicht misschien leuker, maar is om meerdere redenen verkeerd.

  • De bovenstaande regex zou overeenkomen met een verzoek uri van /enjoy, doorverwijzen naar /joy stroomopwaarts. Is dit echt bedoeld?

  • Een verzoek voor /en zal niet resulteren in omleidingen, die direct een / van stroomopwaarts (bijna alsof een verzoek om /en/ is gemaakt, maar niet helemaal). Als u relatieve URI's binnen uw rootpagina stroomopwaarts gebruikt (anders, waarom zou u dan niet de /en/ prefix daar binnen de stroomopwaartse URI's?), b.v. src="style.css" (die naar een taalspecifiek kan verwijzen url("menu.png"), bijvoorbeeld), dan vraagt ​​de browser dat als /style.css in plaats van /en/style.css. (Of zelfs als u overal absolute URI's gebruikt, wat als iemand relatief verwijst naar een obscure semi-optionele bron?) Oeps, ineens werkt de site mogelijk niet, maar slechts soms of in randgevallen.

  • Zoals per mijn eerder advies bij een andere vraag die al is genoemd in het antwoord van het OP zelf, voorkomt het gebruik van reguliere expressies proxy_redirect richtlijn van het hebben van de standaardwaarde van default, verander het naar off in plaats daarvan. Dit betekent dat als de stroomopwaartse antwoorden antwoorden met Location: http://127.0.0.1:8080/en/dir/ wanneer een verzoek voor /en/dir is gemaakt, dan is dat wat de klant zal zien, wat uiteraard niet correct zal werken. (Wat vooral ironisch zou zijn geweest voor a /en aanvraag die regex-gebruik in de eerste plaats aanbeveelt, toch lijdt deze specifieke implementatie in plaats daarvan aan een ander probleem, zoals hierboven al vermeld.) Bovendien, als u al gebruik maakt van de upstream richtlijn, dan kan het extra lelijk worden als u gewoon probeert een aangepast exemplaar te gebruiken, vooral als u meer dan één upstream-server hebt - hoe heeft u een afzonderlijke proxy_redirect voor elk van die? U kunt reguliere expressies gebruiken binnen proxy_redirect, misschien zelfs om een ​​host te matchen, maar wat dan als je in de toekomst beslist om een ​​omleiding tussen domeinen te geven?

Om te proberen een aantal van de bovenstaande punten te behandelen met een enkele op regex gebaseerde locatie, kunnen we het volgende doen (merk op dat in proxy_pass we moesten ook de verwijzing naar een server van een laten vallen upstreamop basis van richtlijnen, te maken proxy_redirect rechttoe rechtaan):

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/;
}

Dus, als je het mij vraagt, de originele oplossing met de twee belangrijkste locaties op hetzelfde niveau zou nog steeds een beter idee zijn dan jezelf in een konijnenhol te graven door in plaats daarvan de regex-route te volgen.


11
2017-10-14 04:51



Dit veroorzaakt een uitzondering: nginx: [emerg] location "/en" is outside location "^/en/?((?<=/).* - Athlan
@Athlan, dat komt omdat je dat eigenlijk niet echt zou moeten gebruiken! Als je dat nog steeds wilt, kun je die locatie buiten de regexp plaatsen. - cnst
puting localation = / nl werkt prima! bedankt - Sebastian Webber


Dus ik vond het antwoord op stackoverloop:

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

Kort gezegd: een regex naar een locatie leiden en de backref doorgeven aan de proxy_pass-URL.


6
2017-12-20 15:30



Ik denk "proxy_pass weelderige / $; "moet" proxy_pass zijn weelderige / $ 2" - Zafer
@Zafer heeft gelijk, het bovenstaande antwoord gaf me een foutmelding - franck
Ik heb het antwoord veranderd, maar heb geen server bij de hand waar ik dit kan proberen, ATM, dus het is niet geverifieerd. - berkes