16 votes

Comment faire en sorte que nginx réécrive les URI dans le contenu du corps HTTP ?

Ceci fait suite à ma question précédente sur la manière de faire en sorte que nginx renvoie le proxy inverse 302 vers un sous-dossier d'URI au lieu de la racine.

J'ai un serveur proxy nginx qui utilise les directives rewrite et proxy_pass pour renvoyer des requêtes externes à une URL comme https://domain.com/my/web/app/ vers un serveur LAN interne à https://10.0.0.22/. Voici ma tentative de représenter la traduction en ASCII UML :

                                    .-------------.       .------------------.
                                    | Proxy nginx  |      | Serveur web local |
                                    | (domain.com) |      | (10.0.0.22)      |
                                    '-------------'       '------------------'
                                               |                 |
                                               |                 |
GET https://domain.com/my/web/app/ ----------->|                 |
                                               |---------------->| GET /
                                               |                 |
                                               |<----------------| 302 redirection /login.php
302 redirection /my/web/app/login.php <-----------|                 |
                                               |                 |
GET https://domain.com/my/web/app/login.php -->|                 |
                                               |---------------->| GET /login.php
                                               |                 |
                                               |<----------------| 200
Contenu du corps HTML (images, CSS, liens) <-------|

Voici le bloc de localisation réel dans mon fichier de configuration nginx :

location ^~ /my/web/app/
{
    proxy_buffering   off;
    rewrite           /my/web/app/(.*) /$1 break;
    proxy_pass        https://10.0.0.22/;
    proxy_redirect    default;
}

Cela fonctionne très bien pour la traduction d'URI entre les chemins d'URI internes et externes pour les requêtes et réponses HTTP, mais toutes les URIs dans le contenu HTML (images du corps, CSS, scripts) ne sont pas traduites.

Par exemple, les images avec des chemins relatifs intégrés dans la réponse HTML, avec des URIs comme /images/logo.png, sont renvoyées au client web et interprétées comme https://domain.com/images/logo.png au lieu de https://domain.com/my/web/app/images/logo.png.

Je peux comprendre pourquoi cela se produit, mais ce serait merveilleux s'il y avait un moyen de renvoyer dynamiquement le contenu ainsi que les requêtes. Est-il possible de faire en sorte que nginx convertisse également les URIs intégrées dans le contenu HTML ? Est-il possible de parser dynamiquement et de mettre à jour le contenu HTML alors qu'il passe par le serveur proxy ?

5voto

Pyromancer Points 21

La seule solution que j'ai trouvée jusqu'à présent est le HttpSubsModule (voir également la page github).

Le module ne fait pas partie des sources officielles de Nginx, donc vous devrez probablement construire vous-même Nginx pour utiliser ce module.

1voto

Camille Points 11

En utilisant le module ngx_http_sub_module, on peut faire quelque chose comme ce qui suit (ajouté dans l'exemple de configuration ci-dessus, juste en dessous de la directive proxy_pass):

    sub_filter_once off;
    sub_filter ' href="http://superuser.com/' ' href="http://superuser.com/my/web/app/';
    sub_filter ' src="/' ' src="/my/web/app/';
    sub_filter ' action="/' ' action="/my/web/app/';

Cela devrait remplacer les URLs de liens dans divers contextes ([, ```![](</code), ``, `, <code><form action=</code>, etc.) pour avoir tout ce qui commence par un <code>/</code> remplacé par <code>/my/web/app/</code>.</p> <p>La première ligne lui indique de continuer à analyser au delà du premier match (essentiel pour obtenir chaque lien dans le HTML résultant); les trois autres lignes mettent à jour les diverses formes de liens et d'identifiants de ressources.</p> <p>Si votre serveur effectue des redirections, vous pourriez aussi avoir besoin de l'une ou plusieurs des lignes suivantes (vous n'avez probablement besoin que d'une seule, mais laquelle dépend un peu du comportement de l'application):</p> <pre><code> proxy_redirect / /my/web/app/; # pour les redirections utilisant simplement / proxy_redirect https://10.0.0.22/ /my/web/app/; # redirections utilisant l'url backend proxy_redirect https://$http_host/ /my/web/app/; # sensibilisation au proxy (voir ci-dessous) </code></pre> <p>Remarque sur ce troisième élément: Au moins dans l'environnement que j'utilisais (une application de test Rails, utilisant http -- donc un peu différente de la vôtre), l'application (Rails) générait un en-tête <code>Location:</code> qui utilisait l'en-tête <code>Host</code> que j'avais passé avec <code>proxy_set_header</code> (dont j'avais besoin pour d'autres raisons), donc cela ressemblait à quelque chose comme: <code>Location: https://example.com/something</code>; donc cette troisième ligne était ce dont j'avais besoin pour pouvoir faire correspondre <code>https://example.com/</code> et le remplacer par <code>/my/web/app/</code>.</p> <p>(Il me semble que j'ai vu quelque part un autre en-tête qui peut être défini pour rendre l'application consciente de l'URL de base pré-proxy, ce qui pourrait rendre cela non nécessaire... mais je n'ai pas réussi à le trouver tout de suite, et cela a fonctionné pour moi, alors...)</p></x-turndown>` `` ```](</code)

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X