Maison > interface Web > js tutoriel > Ingénierie inverse GraphQL persistedQuery extension

Ingénierie inverse GraphQL persistedQuery extension

DDD
Libérer: 2024-11-25 00:44:13
original
347 Les gens l'ont consulté

GraphQL est un langage de requête permettant d'obtenir des données structurées profondément imbriquées à partir du backend d'un site Web, similaire aux requêtes MongoDB.

La requête est généralement un POST vers un point de terminaison général /graphql avec un corps comme celui-ci :

Reverse engineering GraphQL persistedQuery extension

Cependant, avec de grandes structures de données, cela devient inefficace : vous envoyez une requête volumineuse dans un corps de requête POST, qui est (presque toujours) le même et ne change que lors des mises à jour du site Web ; Les requêtes POST ne peuvent pas être mises en cache, etc. Par conséquent, une extension appelée « requêtes persistantes » a été développée. Ce n’est pas un secret anti-grattage ; vous pouvez lire la documentation publique à ce sujet ici.

TLDR : le client calcule le hachage sha256 du texte de la requête et envoie uniquement ce hachage. De plus, vous pouvez éventuellement intégrer tout cela dans la chaîne de requête d'une requête GET, la rendant ainsi facilement mise en cache. Vous trouverez ci-dessous un exemple de demande de Zillow

Reverse engineering GraphQL persistedQuery extension

Comme vous pouvez le voir, il ne s'agit que de quelques métadonnées sur l'extension persistedQuery, le hachage de la requête et les variables à intégrer dans la requête.

Voici une autre demande d'expedia.com, envoyée sous forme de POST, mais avec la même extension :

Reverse engineering GraphQL persistedQuery extension

Cela optimise principalement les performances du site Web, mais cela crée plusieurs défis pour le web scraping :

  • Les requêtes GET sont généralement plus susceptibles d'être bloquées.
  • Paramètres de requête cachés : nous ne connaissons pas la requête complète, donc si le site Web répond avec une erreur « Requête persistante introuvable » (nous demandant d'envoyer la requête dans son intégralité, pas seulement le hachage), nous ne pouvons pas envoie-le.
  • Une fois que le site Web change ne serait-ce qu'un petit peu et que les clients commencent à demander une nouvelle requête - même si l'ancienne fonctionne toujours, le serveur oubliera très vite son ID/hachage, et votre demande avec ce hachage ne fonctionnera jamais. encore une fois, puisque vous ne pouvez pas « rappeler » au serveur le texte complet de la requête.

Par conséquent, pour différentes raisons, vous pourriez vous retrouver dans la nécessité d'extraire l'intégralité du texte de la requête. Vous pouvez parcourir le JavaScript du site Web et, si vous avez de la chance, vous y trouverez peut-être le texte de la requête dans son intégralité, mais souvent, il est construit de manière dynamique à partir de plusieurs fragments, etc.

Par conséquent, nous avons trouvé une meilleure solution : nous ne toucherons pas du tout au JavaScript côté client. Au lieu de cela, nous allons essayer de simuler la situation dans laquelle le client tente d'utiliser un hachage que le serveur ne connaît pas. Par conséquent, nous devons intercepter la requête (valide) envoyée par le navigateur en cours et modifier le hachage en un faux avant de le transmettre au serveur.

Pour exactement ce cas d'utilisation, il existe un outil parfait : mitmproxy, une bibliothèque Python open source qui intercepte les requêtes effectuées par vos propres appareils, sites Web ou applications et vous permet de les modifier avec de simples scripts Python.

Téléchargez mitmproxy et préparez un script Python comme celui-ci :

import json

def request(flow):
    try:
        dat = json.loads(flow.request.text)
        dat[0]["extensions"]["persistedQuery"]["sha256Hash"] = "0d9e" # any bogus hex string here
        flow.request.text = json.dumps(dat)
    except:
        pass
Copier après la connexion

Ceci définit un hook que mitmproxy exécutera à chaque requête : il essaie de charger le corps JSON de la requête, modifie le hachage en une valeur arbitraire et écrit le JSON mis à jour en tant que nouveau corps de la requête.

Nous devons également nous assurer de rediriger les requêtes de notre navigateur vers mitmproxy. Pour cela, nous allons utiliser une extension de navigateur appelée FoxyProxy. Il est disponible dans Firefox et Chrome.

Ajoutez simplement un itinéraire avec ces paramètres :

Reverse engineering GraphQL persistedQuery extension

Nous pouvons maintenant exécuter mitmproxy avec ce script : mitmweb -s script.py

Cela ouvrira un onglet de navigateur où vous pourrez regarder toutes les requêtes interceptées en temps réel.

Reverse engineering GraphQL persistedQuery extension

Si vous accédez au chemin particulier et voyez la requête dans la section requête, vous verrez qu'une valeur inutile a remplacé le hachage.

Reverse engineering GraphQL persistedQuery extension

Maintenant, si vous visitez Zillow et ouvrez le chemin particulier que nous avons essayé pour l'extension, et accédez à la section de réponse, le côté client reçoit l'erreur PersistedQueryNotFound.

Reverse engineering GraphQL persistedQuery extension

Le front-end de Zillow réagit en envoyant l'intégralité de la requête sous forme de requête POST.

Reverse engineering GraphQL persistedQuery extension

Nous extrayons la requête et le hachage directement de cette requête POST. Pour garantir que le serveur Zillow n'oublie pas ce hachage, nous exécutons périodiquement cette requête POST avec exactement la même requête et le même hachage. Cela garantira que le scraper continue de fonctionner même lorsque le cache du serveur est nettoyé ou réinitialisé ou que le site Web change.

Conclusion

Les requêtes persistantes sont un puissant outil d'optimisation pour les API GraphQL, améliorant les performances du site Web en minimisant la taille des charges utiles et en activant la mise en cache des requêtes GET. Cependant, ils posent également des défis importants pour le web scraping, principalement en raison de la dépendance aux hachages stockés sur le serveur et du risque que ces hachages deviennent invalides.

L'utilisation de mitmproxy pour intercepter et manipuler les requêtes GraphQL offre une approche efficace pour révéler le texte complet de la requête sans se plonger dans du JavaScript complexe côté client. En forçant le serveur à répondre avec une erreur PersistedQueryNotFound, nous pouvons capturer la charge utile complète de la requête et l'utiliser à des fins de scraping. L'exécution périodique de la requête extraite garantit que le scraper reste fonctionnel, même lorsque des réinitialisations du cache côté serveur se produisent ou que le site Web évolue.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:dev.to
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal