În primul rând, dvs ^/(123[0-9])$
regex se va potrivi numai /1234
URI (sau /1230
, /1231
, etc.) dar nu /1234/unele/cale
din moment ce utilizați $
ancoră de capăt de sfoară. Presupun că nu este o eroare, ci o soluție de proiectare. Dacă nu este, să se potrivească pe ambele /1234
și /1234/unele/cale
(dar nu ceva de genul /12345
), puteți folosi o alternativă: ^/(123[0-9])(?:/|$)
(Folosesc un grup fără captură (?:...)
aici, deoarece se consideră că are performanțe puțin mai bune decât grupul de captură).
Configurația dvs. are o grămadă de greșeli diferite. Să ne uităm peste fiecare.
Greșeala nr. 1: incorectă rescrie... ultimul;
utilizare.
Într-adevăr, nu puteți specifica un URI pentru proxy_pass
în amonte, așa cum încercați să faceți cu un slash final
proxy_pass http://localhost:$1/; # adăugare bară oblică nu este permisă
în interiorul locațiilor de potrivire regex (precum și în interiorul locațiilor numite) și singura modalitate de a schimba URI-ul care va fi transmis backend-ului este să utilizați rescrie
directivă. Cu toate acestea, modul corect de a schimba un URI în interiorul Locație
bloc pentru a-l procesa mai târziu în aceeași locație este de utilizat rescrie... pauză;
de cand rescrie... ultimul;
va forța nginx să caute o nouă locație pentru URI-ul rescris. Asta înseamnă că trebuie să folosim pauză
steag pentru rescrie
directivă:
rescrie ^/[0-9]{4}(.*)$ $1 pauză;
Ai grijă! Fără directive de la ngx_http_rewrite_module
va fi executat după rescrie... pauză;
(sau pur și simplu pauză;
) directiva (Actualizați: după unele teste, spre deosebire de ceea ce se spune în documentație, se dovedește că este adevărat numai pentru pauză
directiva dar nu rescrie... pauză
unul, cel puțin pentru OpenResty 1.17.8.2 bazat pe nucleul nginx 17.8).
Greșeala #2: Ar trebui să citați orice șir care conține paranteze sau acestea vor fi considerate ca bloc de configurare nginx.
Directiva anterioară ne va da următoarea eroare:
nginx: directiva [emerg] „rewrite” nu este terminată cu „;”
Pentru a scăpa de această eroare, trebuie să menționăm modelul nostru regex din cauza utilizării parantezelor:
rescrie „^/[0-9]{4}(.*)$” $1 pauză;
Greșeala #3: Capturile numerotate sunt suprascrise ori de câte ori se evaluează expresia regulată.
Să presupunem că aveți un URI de /1234
:
locație ~ ^/(123[0-9])$ {
# Aici valoarea variabilei „$1” este „1234”
rescrie „^/[0-9]{4}(.*)$” $1 pauză;
# Aici valoarea variabilei „$1” este un șir gol!
proxy_pass http://localhost:$1; # Nu va exista niciun port pentru directiva „proxy_pass”.
}
Poți salva asta $1
valoare înainte ca regula de rescrire să-și evalueze propria expresie regulată folosind a stabilit
directivă:
locație ~ ^/(123[0-9])$ {
setează $port $1;
rescrie „^/[0-9]{4}(.*)$” $1 pauză;
proxy_pass http://localhost:$port;
}
sau mai bine folosiți numit grup de captură:
locație ~ ^/(?<port>123[0-9])$ {
rescrie „^/[0-9]{4}(.*)$” $1 pauză;
proxy_pass http://localhost:$port;
}
Uneori nu poate exista altă soluție decât să folosești capturi cu nume, un exemplu excelent al unei astfel de situații este dat la acest fir.
Greșeala #4: URI-ul rescris nu poate fi un șir gol.
Din nou, să presupunem că aveți un URI de /1234
. După regula de rescriere, un nginx intern $uri
variabila va avea o valoare goală. Acest lucru ar duce la o eroare HTTP 500 Internal Server, iar în jurnalul de erori nginx veți vedea următorul mesaj de eroare:
URI-ul rescris are o lungime zero
Pentru a rezolva această eroare, trebuie doar să rescrieți orice URI în /
:
locație ~ ^/(?<port>123[0-9])$ {
rescrie ^ / break;
proxy_pass http://localhost:$port;
}
Dacă ar trebui să serviți vreunul /<port_number>/some/path
cerere ca mai sus, ar trebui să utilizați următorul bloc de locație pentru a vă asigura că URI-ul rescris începe cu o bară oblică:
locație ~ ^/(?<port>123[0-9])(?:/|$) {
rescrie "^/\d{4}(?:/(.*))?" /$1 pauză;
proxy_pass http://localhost:$port;
}
Greșeala #5: Trebuie să specificați un resolver atunci când utilizați variabile cu proxy_pass
directivă.
Configurația de mai sus este aproape de soluția de lucru. Cu toate acestea, este încă nefuncțional, dându-vă o eroare HTTP 502 Bad Gateway. Trebuie să specificați a rezolutor
atunci când utilizați variabile cu proxy_pass
directivă și în amonte este specificată de numele domeniului și nu de adresa IP, altfel veți primi următoarea eroare în jurnalul de erori nginx:
nici un rezolutor definit pentru a rezolva localhost
În general, ar trebui să folosești ceva de genul
rezolutor 8.8.8.8;
locație ~ ^/(?<port>123[0-9])$ {
rescrie ^ / break;
proxy_pass http://localhost:$port;
}
dar din moment ce dvs. în amonte este gazdă locală
, puteți specifica adresa sa IP în loc de numele domeniului, astfel nu veți avea nevoie de asta rezolutor
directivă la toate:
locație ~ ^/(?<port>123[0-9])$ {
rescrie ^ / break;
proxy_pass http://127.0.0.1:$port;
}
Această configurație ar trebui să fie pe deplin funcțională (în sfârșit). Și încă o dată, dacă ar trebui să serviți vreunul /<port_number>/some/path
cerere ca mai sus, ar trebui să utilizați în schimb următorul bloc de locație:
locație ~ ^/(?<port>123[0-9])(?:/|$) {
rescrie "^/\d{4}(?:/(.*))?" /$1 pauză;
proxy_pass http://127.0.0.1:$port;
}