Come rimuovere il percorso con un proxy_pass nginx


77

Ho un'applicazione web in esecuzione su http://example.com/e desidero "montare" un'altra applicazione su un server separato su http://example.com/en. Server a monte e proxy_passsembrano funzionare, ma per un problema:

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

All'apertura example.com/en, la mia applicazione upstream ritorna 404 not found /en. Questo ha senso, poiché l'upstream non ha il percorso /en.

È proxy_pathla soluzione giusta? Dovrei riscrivere "upstream" in modo che ascolti /eninvece, come percorso root? Oppure esiste una direttiva che mi consente di riscrivere il percorso passato a monte?

Risposte:


134

Questo è probabilmente il modo più efficiente per fare ciò che vuoi, senza l'uso di espressioni regolari:

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

1
Per quanto ne so, l'ultima parte passerebbe comunque "/ en" come percorso al proxy, no?
Berkes,

15
@berkes, no, non lo farà - la barra finale proxy_passè ciò che fa la differenza. Inoltre, questa risposta è più corretta di quella che ti è venuta in mente, perché garantisce anche che proxy_redirectrimanga default, quindi, puoi comunque usare 302et al nel tuo backend e farlo funzionare correttamente ovunque.
primo

4
Ah, mi mancava la barra finale :(
Vanuan

3
AAARGH! TRAILING SLASH!
Barrymac,

4
3 ore di ricerche, e sì ... Era la barra finale. Grazie compagno!
Lucas P.

12

Vorrei rivolgermi a una nuova risposta basata sulla regex che sta diventando sempre più popolare.

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

La soluzione può sembrare più carina a prima vista, ma è sbagliata per diversi motivi.

  • Il regex di cui sopra corrisponderebbe a un uri di richiesta /enjoy, reindirizzandolo a /joymonte. È davvero previsto?

  • Una richiesta per /ennon comporterà alcun reindirizzamento, servendo direttamente una a /monte (quasi come se /en/fosse invece fatta una richiesta per , ma non del tutto). Se usi URI relativi all'interno della tua pagina radice a monte (altrimenti, perché non dovresti avere il /en/prefisso proprio lì all'interno degli URI a monte?), Ad esempio src="style.css"(che potrebbe fare riferimento a una lingua specifica url("menu.png"), ad esempio), allora il browser richiederà che come /style.cssinvece di /en/style.css. (O anche se usi URI assoluti ovunque, cosa succede se qualcuno fa riferimento a una risorsa semi-opzionale oscura relativamente?) Spiacenti, improvvisamente il sito potrebbe non funzionare, ma solo a volte o in casi limite.

  • Secondo il mio precedente consiglio a un'altra domanda già menzionata dalla risposta stessa del PO , l'uso di espressioni regolari impedisce alla proxy_redirectdirettiva di avere il valore predefinito di default, rifiutandolo offinvece. Ciò significa che se l'upstream risponde Location: http://127.0.0.1:8080/en/dir/quando /en/dirviene fatta una richiesta , allora è quello che vedrà il client, che ovviamente non funzionerà correttamente. (Il che sarebbe stato particolarmente ironico per una /enrichiesta che richiede in primo luogo l'uso di regex, tuttavia questa implementazione specifica soffre invece di un altro problema come già menzionato sopra.) Inoltre, se stai già utilizzando ilupstreamdirettiva, quindi potrebbe diventare molto brutto se provi ad usarne uno personalizzato, soprattutto se potresti avere più di un server upstream - come ne hai uno separato proxy_redirectper ognuno di questi? Potresti usare anche espressioni regolari all'interno proxy_redirect, forse anche per abbinare qualsiasi host, ma cosa succederebbe se decidessi di effettuare un reindirizzamento interdominio in futuro?

Per provare ad affrontare alcuni dei punti precedenti con una singola posizione basata su regex, potremmo fare quanto segue (si noti che in proxy_passanche abbiamo dovuto eliminare il riferimento a un server da una upstreamdirettiva basata su, per rendere proxy_redirectpiù semplice):

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

Quindi, se me lo chiedi, la soluzione originale con le due posizioni di livello superiore dei fratelli sarebbe comunque un'idea migliore che scavare te stesso in una tana di coniglio seguendo invece la via regex.


Ciò provoca un'eccezione:nginx: [emerg] location "/en" is outside location "^/en/?((?<=/).*
Athlan il

1
@Athlan, è perché non dovresti davvero usarlo in primo luogo! Se vuoi ancora, puoi mettere quella posizione fuori dal regexp.
primo

mettere localation = / en outside funziona davvero bene! grazie
Sebastian Webber,

7

Quindi, ho trovato la risposta su 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;
  }
}

Fondamentalmente: passare una regex in posizione e passare il backref lungo all'URL proxy_pass.


Penso che "proxy_pass luscious / $ ;" dovrebbe essere "proxy_pass luscious / $ 2 "
Zafer

1
@Zafer ha ragione, la risposta sopra mi stava dando un errore
franck,

Ho cambiato la risposta, ma non ho un server a portata di mano dove posso provare questo, ATM, quindi non è verificato.
Berkes,

0

Contabilità per documenti Nginx

Per passare una richiesta a un server proxy HTTP, la direttiva proxy_pass è specificata all'interno di una posizione. Per esempio:

location /some/path/ {
    proxy_pass http://www.example.com/link/;
}

Questa configurazione di esempio comporta il passaggio di tutte le richieste elaborate in questa posizione al server proxy all'indirizzo specificato. Questo indirizzo può essere specificato come nome di dominio o indirizzo IP. L'indirizzo può anche includere una porta:

location ~ \.php {
    proxy_pass http://127.0.0.1:8000;
}

Si noti che nel primo esempio sopra, l'indirizzo del server proxy è seguito da un URI, / link /. Se l'URI viene specificato insieme all'indirizzo, sostituisce la parte dell'URI di richiesta che corrisponde al parametro location. Ad esempio, qui la richiesta con l'URI /some/path/page.html verrà inoltrata a http://www.example.com/link/page.html . Se l'indirizzo viene specificato senza un URI o non è possibile determinare la parte dell'URI da sostituire, viene passato l'URI della richiesta completa (possibilmente modificato).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.