web-dev-qa-db-fra.com

Proxy inverse Nginx + réécriture d'URL

Nginx fonctionne sur le port 80, et je l'utilise pour inverser les URL proxy avec le chemin /foo au port 3200 par ici:

location /foo {
                proxy_pass http://localhost:3200;
                proxy_redirect     off;
                proxy_set_header   Host $Host;
}

Cela fonctionne bien, mais j'ai une application sur le port 3200, pour lequel je ne veux pas la première /foo à envoyer. Autrement dit, lorsque j'accède à http://localhost/foo/bar, Je veux seulement /bar pour être le chemin tel que reçu par l'application. J'ai donc essayé d'ajouter cette ligne au bloc d'emplacement ci-dessus:

rewrite ^(.*)foo(.*)$ http://localhost:3200/$2 permanent;

Cela provoque la redirection 302 (changement d'URL), mais je veux 301. Que dois-je faire?

172
jeffreyveon

Toute redirection vers localhost n'a aucun sens à partir d'un système distant (par exemple, le navigateur Web du client). Ainsi, les drapeaux de réécriture permanent (301) ou redirection (302) ne sont pas utilisables dans votre cas.

Veuillez essayer de suivre la configuration en utilisant une règle de réécriture transparente:

location  /foo {
  rewrite /foo/(.*) /$1  break;
  proxy_pass         http://localhost:3200;
  proxy_redirect     off;
  proxy_set_header   Host $Host;
}

Utilisation curl -i pour tester vos réécritures. Une modification très subtile de la règle peut amener nginx à effectuer une redirection.

188
Jens Bradler

La correspondance de préfixe d'emplacement simple fonctionne pour cela sans utiliser de règle de réécriture tant que vous spécifiez un URI dans la directive proxy_pass:

location /foo {
  proxy_pass http://localhost:3200/;
}

Remarquez le / à la fin de proxy_pass directive. NGINX supprimera le préfixe correspondant /foo et passez le reste au serveur principal à l'URI /. Par conséquent, http://myserver:80/foo/bar publiera sur le backend à http://localhost:3200/bar.

À partir des documents NGINX sur proxy_pass :

Si la directive proxy_pass est spécifiée avec un URI, alors lorsqu'une demande est transmise au serveur, la partie d'un URI de demande normalisée correspondant à l'emplacement est remplacée par un URI spécifié dans la directive:

146
DanArl

La manière la plus correcte et la meilleure pratique absolue est généralement la suivante:

location /foo/ {
    proxy_pass http://localhost:3200/; # note the trailing slash!
}

  • Notez la grande importance de la barre oblique de fin dans proxy_pass, qui modifie automatiquement la $uri Pour que le /foo/ Sur le front-end corresponde à / Sur le backend. Pas besoin d'une directive rewrite explicite.

  • De plus, notez que le suivi de / Dans le location est assez important aussi - sans cela, vous risquez d'avoir des URL d'aspect étrange sur votre site à un moment donné (par exemple, un /fooen en plus de /foo/en).

    De plus, la fin de / Dans le location avec proxy_pass Garantit également un certain traitement spécial, selon la documentation de la directive location, pour provoquer efficacement un location = /foo {return 301 /foo/;} implicite également.

    Ainsi, en définissant un location avec la barre oblique de fin comme ci-dessus, vous vous assurez non seulement que les URL de suffixe sans barre oblique comme /fooen Ne seront pas valides, mais aussi qu'un /foo sans barre oblique continue également.


Documentation de référence:

71
cnst

essayer

location /foo {
    proxy_pass http://localhost:3200/;
    ....

ou

location ^~ /foo {
    proxy_pass http://localhost:3200/;
    ....
2
DerGeh

@Terabuck Désolé de ne pas avoir encore répondu aucun représentant.

Vous ne devez pas utiliser localhost car vous dépendez du fait que l'application s'exécute sur un serveur avec un fichier hosts. l'hôte local n'est qu'une traduction par défaut de 127.0.0.1. Rien ne dit que vous devez avoir ces fichiers hôtes. Il est très courant d'en avoir un.

Avoir une interface de bouclage est encore une fois une chose courante sur laquelle compter, mais vous dépendez toujours de l'interface de bouclage sur la pile réseau. C'est un cas rare de ne pas avoir ces deux-là. Si jamais vous vous en souciez. Au moins sur unix/linux, vous avez l'option pour les sockets. Cela éliminera la nécessité pour la pile réseau d'atteindre l'hôte local. Soyez prudent avec cette approche car il y a quelques facteurs qui se mettront en place sur le système d'exploitation hôte. Tels que le nombre de fichiers ouverts, etc.

1
Cody Van Lith