web-dev-qa-db-fra.com

Comment supprimer le chemin avec un proxy_pass nginx

J'ai une application Web en cours d'exécution sur http://example.com/, et souhaitez "monter" une autre application, sur un serveur distinct sur http://example.com/en. Serveurs en amont et proxy_pass semble fonctionner, mais pour un problème:

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

Lors de l'ouverture example.com/en, mon application en amont renvoie 404 not found /en. Cela a du sens, car l'amont n'a pas le chemin /en.

Est proxy_path la bonne solution? Dois-je réécrire "en amont" pour écouter /en à la place, comme chemin racine? Ou existe-t-il une directive qui me permette de réécrire le chemin emprunté en amont?

93
berkes

C'est probablement le moyen le plus efficace de faire ce que vous voulez, sans utiliser d'expressions régulières:

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

J'aimerais aborder une nouvelle réponse basée sur les expressions rationnelles qui gagne en popularité.

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

La solution peut sembler plus mignonne à première vue, mais elle est fausse pour plusieurs raisons.

  • Le regex ci-dessus correspondrait à un uri de demande de /enjoy, Le redirigeant vers /joy En amont. Est-ce vraiment prévu?

  • Une demande de /en N'entraînera aucune redirection, servant directement un / Depuis l'amont (presque comme si une demande de /en/ Avait été faite à la place, mais pas tout à fait). Si vous utilisez des URI relatifs dans votre page racine en amont (sinon, pourquoi n'auriez-vous pas le préfixe /en/ Juste là dans les URI en amont?), Par exemple src="style.css" (Qui peut faire référence à une url("menu.png") spécifique à une langue, par exemple), le navigateur demandera cela en tant que /style.css Au lieu de /en/style.css. (Ou même si vous utilisez des URI absolus partout, que se passe-t-il si quelqu'un fait référence à une ressource semi-facultative obscure relativement?) Oups, soudainement, le site peut ne pas fonctionner, mais seulement parfois ou dans les cas Edge.

  • Selon mon conseil précédent à une autre question déjà mentionnée par la réponse du PO , l'utilisation d'expressions régulières empêche la directive proxy_redirect d'avoir la valeur par défaut de default, en le diminuant à off à la place. Cela signifie que si l'amont répond par Location: http://127.0.0.1:8080/en/dir/ Lorsqu'une demande de /en/dir Est faite, c'est ce que le client verra, ce qui ne fonctionnera évidemment pas correctement. (Ce qui aurait été particulièrement ironique pour une demande /en Qui invite à utiliser regex en premier lieu, mais cette implémentation spécifique souffre à la place d'un autre problème comme déjà mentionné ci-dessus.) De plus, si vous utilisez déjà le - upstream , alors cela peut devenir très moche si vous essayez de choisir un serveur personnalisé, surtout si vous pouvez avoir plus d'un serveur en amont - comment avez-vous un proxy_redirect Pour chacun d'entre eux? Vous pouvez également utiliser des expressions régulières dans proxy_redirect, Peut-être même pour correspondre à n'importe quel hôte, mais que se passe-t-il si vous décidez de donner une redirection entre domaines à l'avenir?

Pour essayer de résoudre certains des points ci-dessus avec un seul emplacement basé sur une expression régulière, nous pouvons procéder comme suit (notez que dans proxy_pass, Nous avons également dû supprimer la référence à un serveur à partir d'un upstream -based directive, pour rendre proxy_redirect plus simple):

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

Donc, si vous me demandez, la solution originale avec les deux emplacements supérieurs de la fratrie serait toujours une meilleure idée que de vous enfoncer dans un terrier de lapin en empruntant plutôt la route des regex.

12
cnst

Donc, j'ai trouvé le réponse sur 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;
  }
}

Fondamentalement: passer un regex à l'emplacement et passer la backref à l'url proxy_pass.

6
berkes

Comptabilisation documents Nginx

Pour transmettre une demande à un serveur proxy HTTP, la directive proxy_pass est spécifiée à l'intérieur d'un emplacement. Par exemple:

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

Cet exemple de configuration entraîne le transfert de toutes les demandes traitées à cet emplacement au serveur mandaté à l'adresse spécifiée. Cette adresse peut être spécifiée comme un nom de domaine ou une adresse IP. L'adresse peut également inclure un port:

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

Notez que dans le premier exemple ci-dessus, l'adresse du serveur mandaté est suivie d'un URI,/link /. Si l'URI est spécifié avec l'adresse, il remplace la partie de l'URI de demande qui correspond au paramètre d'emplacement. Par exemple, ici, la demande avec l'URI /some/path/page.html sera envoyée par proxy à http://www.example.com/link/page.html . Si l'adresse est spécifiée sans URI, ou s'il n'est pas possible de déterminer la partie d'URI à remplacer, l'URI de demande complète est transmis (éventuellement, modifié).

0
Jeff