web-dev-qa-db-fra.com

Modifier la réponse HTML (pas les en-têtes)

En espérant que quelqu'un puisse m'aider ou me diriger dans la bonne direction.

On m'a demandé de savoir comment faire en sorte qu'Akamai (ou tout autre CDN ou NGINX) modifie le corps de réponse réel.

Pourquoi?

Je dois faire en sorte que le CDN change toutes les demandes "http: //" en "https: //" au lieu de modifier le code de l'application pour utiliser "//" pour les demandes de ressources externes.

Est-ce possible?

Quelqu'un sait?

19
Charlie

Cela semble être possible via un certain nombre d'approches différentes, mais cela ne veut pas dire comment souhaitable cela pourrait être le cas.

Cela semble potentiellement problématique (exemple: que se passe-t-il si vous réécrivez quelque chose qui n'aurait pas dû être réécrit?) Et gourmand en ressources machine (beaucoup de cycles CPU pour analyser et munger les corps de réponse, à plusieurs reprises).

Voici ce que j'ai trouvé:

Nginx a le http_sub_module qui semble accomplir cela d'une manière assez simple, en supposant que ce que vous voulez remplacer est simple et que vous n'avez besoin de faire correspondre qu'un seul modèle par page, comme remplacer <a href="http://example.com/... avec <a href="https://example.com/..., une ou plusieurs fois. Ce type de contenu-mungery semble sommaire, mais selon la situation dans laquelle vous vous trouvez (qui peut être un contrôle limité de l'application), il pourrait obtenir Toi là.

Il semble qu'il y ait quelque chose appelé http_substitutions_filter , peut-être non officiel ou du moins ne faisant pas partie de la distribution Nginx de base qui peut effectuer une réécriture de filtres plus puissante basée sur un filtre.

Varnish semble avoir une capacité similaire (peut-être un plugin) mais HAProxy pas , car il ne traite que les en-têtes et laisse les corps seuls, sauf lors du déchargement gzip. D'autres logiciels compatibles avec le proxy inverse comme Apache ou Squid pourraient également offrir quelque chose d'utile, que vous placeriez devant votre serveur d'applications.

Mon impression initiale, en tout état de cause, est que le simple remplacement de chaîne peut ne pas vous y arriver, et même le remplacement basé sur des expressions régulières n'est pas vraiment suffisant, sans une sophistication significative des expressions régulières, car vous courez toujours le risque de réécrire quelque chose que vous ne devrait pas.

Ce que je suggérerais "doit vraiment se produire" pour atteindre cet objectif de la manière la plus correcte, serait d'interpréter réellement le code HTML généré avec une bibliothèque d'analyse DOM, de parcourir l'arborescence et de modifier les éléments pertinents sur place, avant remettre le document révisé au demandeur. De cette façon, le document est modifié en fonction d'une compréhension contextuelle de son contenu.

Cela semble compliqué, à mon avis, car c'est le cas - je vous suggère donc à nouveau de reconsidérer votre approche, à moins que cela ne soit hors de votre contrôle.

Pensée finale: Curiosity a eu le meilleur de moi, j'ai donc pris cette question et mis à niveau le proxy inverse http que j'ai écrit (dans un but différent) afin que, en fonction du type de contenu, il puisse réellement analyser et parcourir la structure HTML en tant que entité appropriée, en la modifiant en place (comme décrit ci-dessus), avant de renvoyer le corps de réponse au demandeur.

Comme je m'y attendais, cela s'avère assez gourmand en ressources processeur. Mon contenu de test était de 29 Ko de HTML réel provenant d'un site en direct, contenant 56 <a href ...> et 6 <link rel ...> éléments, et l'opération de réécriture a nécessité 128 ms sur un Opteron 1218 1 GHz et 43 ms 2,4 GHz Xeon E5620. Ces repères sont strictement pour les opérations supplémentaires - à l'exclusion du temps (moindre) requis pour la fonctionnalité "proxy" elle-même. Ce coût en temps n'est pas insurmontable, mais pourrait représenter beaucoup de temps CPU. C'est beaucoup plus long qu'une réécriture de contenu basé sur une expression régulière, mais c'est beaucoup plus précis et il est peu probable qu'il casse les pages qu'il touche.

14
Michael - sqlbot

Le HttpSubsModule de Nginx a très bien fonctionné pour moi: http://wiki.nginx.org/HttpSubsModule

Passer de http à https devrait être aussi simple que cela:

location / {
    subs_filter_types text/html text/css text/xml;
    subs_filter http.example.com https.example.com gi;
}
10
Raptor

Syntaxe identique mais correcte.

location / {
    sub_filter_types text/html text/css text/xml;
    sub_filter 'http.example.com' 'https.example.com';
}
7
Arnaud Weil