Nginx Redirect via proxy, réécrire et préserver l'URL

Dans Nginx, nous essayons de redirect une URL comme suit:

http://example.com/some/path -> http://192.168.1.24 

où l'user voit toujours l'URL d'origine dans son browser. Une fois que l'user est redirigé, disent qu'ils cliquent sur le lien vers /section/index.html , nous voudrions que cela fasse une requête qui conduit à la redirection

 http://example.com/some/path/section/index.html -> http://192.168.1.24/section/index.html 

et conserve encore l'URL originale.

Nos tentatives ont impliqué diverses solutions utilisant des proxies et des règles de réécriture, et ci-dessous montre la configuration qui nous a amenés le plus près d'une solution (notez qu'il s'agit de la configuration du server Web pour le server web example.com ). Cependant, il existe encore deux problèmes avec ceci:

  • Il n'effectue pas la réécriture correcte, en ce que l'URL de requête reçue par le server Web http://192.168.1.24 comprend /some/path et ne parvient donc pas à servir la page requirejse.
  • Lorsque vous vous déplacez sur un lien une fois qu'une page a été diffusée, /some/path est absent de l'URL

     server { listn 80; server_name www.example.com; location /some/path/ { proxy_pass http://192.168.1.24; proxy_redirect http://www.example.com/some/path http://192.168.1.24; proxy_set_header Host $host; } location / { index index.html; root /var/www/example.com/htdocs; } } 

Nous recherchons une solution qui ne comporte que la modification de la configuration du server Web sur example.com . Nous sums en mesure de modifier la configuration sur 192.168.1.24 (également Nginx), mais nous voulons essayer de l'éviter car nous devrons répéter cette configuration pour des centaines de servers différents dont l'access dépend de example.com .

    Tout d'abord, vous ne devez pas utiliser root directive root dans le bloc d'location, c'est une mauvaise pratique. Dans ce cas, cela n'a pas d'importance.

    Essayez d'append un deuxième bloc d'location:

     location ~ /some/path/(?<section>.+)/index.html { proxy_pass http://192.168.1.24/$section/index.html; proxy_set_header Host $host; } 

    Ceci capture la partie après / certains / path / et avant index.html à une variable $ section, qui est ensuite utilisée pour définir la destination proxy_pass. Vous pouvez rendre la regex plus spécifique si vous avez besoin.

    Vous devez utiliser la partie URI dans la directive proxy_pass . En outre, vous avez mélangé les arguments d' proxy_redirect directive proxy_redirect , et probablement vous n'en avez pas besoin du tout. Nginx a un défaut raisonnable pour cette directive.

    Dans ce cas, votre bloc de location pourrait être très simple:

     location /some/path/ { proxy_pass http://192.168.1.24/; # note this slash -----------^ proxy_set_header Host $host; } 

    Lorsque cette barre oblique est ajoutée à un nginx proxied jenkins, vous êtes présenté avec l'erreur "Il semble que votre proxy inversé est bloqué".

     proxy_pass http://localhost:8080/; Remove this -----------------------------^ 

    Il devrait être lu

     proxy_pass http://localhost:8080; 

    Vous pouvez utiliser la configuration suivante pour avoir un mappage 100% sans soudure entre /some/path/ sur le front-end et / sur le backend.

    Notez que c'est la seule réponse qui permettrait de prendre en charge de façon transparente des paths absolus générant 404 Not Found Erreurs 404 Not Found , pourvu que l'en-tête HTTP Referer correct soit envoyé par le browser, de sorte que tous ces gifs devraient continuer à charger sans avoir besoin de modifiez le HTML sous-jacent (ce qui n'est pas seulement coûteux, mais n'est pas supporté sans modules supplémentaires non compilés par défaut).

     location /some/path/ { proxy_pass http://192.168.1.24/; # note the trailing slash! } location / { error_page 404 = @404; return 404; # this would normally be `try_files` first } location @404 { add_header Vary Referer; # sadly, no effect on 404 if ($http_referer ~ ://[^/]*(/some/path|/the/other)/) { return 302 $1$uri; } return 404 "Not Found\n"; } 

    Vous pouvez find le produit complet de preuve-de-concept et minimal-viable dans le repository https://github.com/cnst/StackOverflow.cnst.nginx.conf .

    Voici un essai pour confirmer que tous les cas de bord semblent fonctionner:

     curl -v -H 'Referer: http://example.su/some/path/page.html' localhost:6586/and/more.gif | & fgrep -e HTTP/ -e Referer -e Location > GET /and/more.gif HTTP/1.1 > Referer: http://example.su/some/path/page.html < HTTP/1.1 302 Moved Temporarily < Location: http://localhost:6586/some/path/and/more.gif < Vary: Referer curl -v localhost:6586/and/more.gif | & fgrep -e HTTP/ -e Referer -e Location > GET /and/more.gif HTTP/1.1 < HTTP/1.1 404 Not Found curl -v localhost:6586/some/path/and/more.gif | & fgrep -e HTTP/ -e Referer -e Location -e uri > GET /some/path/and/more.gif HTTP/1.1 < HTTP/1.1 200 OK request_uri: /and/more.gif 

    PS Si vous avez beaucoup de paths différents à mapper, alors au lieu de faire une comparaison regex de $http_referer dans un if dans l' location @404 , vous voudrez peut-être utiliser la directive de map globale.

    Notez également que les barres obliques à la fois dans proxy_pass , ainsi que dans l' location dans proxy_pass il se trouve, sont très importantes selon une réponse connexe .

    Les references: