Apprendre à votre programme Go à parler comme Chrome

Si vous avez déjà voyagé à l'étranger et commandé un café avec une phrase parfaite sortie d'un manuel, vous connaissez le regard que vous adresse le barista. Votre grammaire est correcte. Chaque mot figure dans le dictionnaire. Et pourtant, en une demi-seconde, tout le monde dans le café sait que vous venez d'ailleurs.
Le client HTTP standard de Go souffre un peu de ce problème. C'est une excellente option par défaut : fiable, épuré et prêt pour un travail sérieux dès l'installation. Cependant, lorsque votre programme se connecte à un serveur, il ressemble indubitablement à un programme Go. La plupart du temps, cela ne pose pas de problème. Néanmoins, certains sites web, réseaux de diffusion de contenu (CDN) et environnements de test prêtent une attention particulière à l'identité de celui qui frappe à la porte, et ils se comportent très différemment selon le type de client auquel ils pensent avoir affaire.
C'est pourquoi nous avons développé gosuda.org/chromenet. Plutôt que d'entraîner le client standard de Go à imiter tant bien que mal un navigateur, chromenet permet à un programme Go de communiquer avec le web grâce au même moteur réseau que Google Chrome, à savoir le code réseau de Chromium lui-même. Que vous souhaitiez vérifier la manière dont vos propres environnements de test traitent le trafic des navigateurs ou dialoguer avec un site protégé par un CDN exigeant, passer par le moteur de Chrome supprime toute une couche d'incertitude.
Vous n'avez pas besoin de réécrire votre application pour l'utiliser. Dans votre code, il fonctionne comme un remplacement direct de http.Transport. Vous continuez à utiliser http.Client comme vous le faites toujours, et chromenet gère les échanges en arrière-plan.
Pour essayer la dernière version, installez-la avec go get :
1go get gosuda.org/chromenet@v0.2.10157081033800
Puis transmettez son transport à votre client :
1client := http.Client{
2 Transport: chromenet.NewTransport(chromenet.Options{}),
3}
Avec cette version, l'ensemble du trafic web moderne transite par le moteur de Chrome. Cela inclut désormais les requêtes web ordinaires, WebSocket et WebTransport. Les versions précédentes ne traitaient correctement que les requêtes ordinaires, tandis que WebSocket et WebTransport n'étaient que des substituts. Ainsi, votre salutation initiale à la porte sonnait comme Chrome, mais si vous passiez à un autre type d'échange, votre déguisement pouvait se trahir. Cette version remplace ces substituts par les véritables implémentations.
Attendez, si nous utilisons le code réseau de Chromium, cela signifie-t-il que votre discret programme Go se transforme en un casse-tête de compilation C envahissant ? Heureusement, non. Votre code Go reste du Go pur, sans cgo ni compilateur C nécessaire.
Plutôt que d'intégrer du code de navigateur directement dans votre binaire, chromenet fait tourner le moteur comme un petit programme distinct à côté de votre programme Go. Imaginez-le comme un interprète local bilingue qui vous accompagne, plutôt que comme une tentative de reconstruire vos propres cordes vocales. Comme le moteur s'exécute dans ce programme séparé, un plantage à l'intérieur de celui-ci ne peut pas interrompre votre service.

Votre programme Go reste du Go pur, tandis qu'un petit programme compagnon achemine le trafic via le moteur réseau de Chromium.
Il n'y a rien de supplémentaire à installer sur votre poste de travail ou sur vos serveurs. Les binaires du moteur pour Linux, macOS et Windows, sur architectures Intel/AMD et ARM, sont intégrés directement dans le module Go et sont vérifiés avant leur exécution.
L'intégration de binaires dans un module soulève naturellement une question pour quiconque se soucie de la confiance, et nous avons voulu y apporter une réponse claire. Les binaires sont construits de manière reproductible à partir d'une version spécifique de Chromium, actuellement Chromium 157, de sorte que chacun peut les reconstruire et obtenir exactement les mêmes octets, et chaque version est attestée par GitHub. Pour suivre l'évolution du navigateur sans intervention manuelle, une tâche planifiée suit le canal stable de Chromium et met à jour automatiquement la version dès qu'une nouvelle version de Chrome est publiée.
Qu'en est-il d'uTLS ?
Si vous avez déjà essayé de faire ressembler un client Go à un navigateur, vous avez probablement rencontré uTLS. C'est une réalisation remarquable : une bibliothèque Go qui permet de revêtir le tout premier message d'une connexion sécurisée pour qu'il ressemble à celui de Chrome, de Firefox ou de tout autre navigateur de votre choix. Elle est légère, écrite en Go pur, et rien d'autre ne s'exécute aux côtés de votre programme.
La limite réside dans l'étendue de ce déguisement. uTLS couvre la négociation initiale, c'est-à-dire les premiers échanges de la conversation. Tout le reste reste à construire de votre côté : la couche HTTP/2 doit être mise en place et réglée manuellement, HTTP/3 constitue une aventure distincte, et WebSocket ou WebTransport exigent encore davantage d'intégration. Les préréglages Chrome sont par ailleurs des copies, et quelqu'un doit les mettre à jour à chaque fois que Chrome modifie ses habitudes. C'est un peu comme imiter l'accent d'une personne alors que le reste de son langage corporel vous trahit.
chromenet suit la voie inverse. Il n'imite pas Chrome : il confie la conversation au moteur même de Chrome. Ainsi, la négociation initiale, la manière dont les connexions sont réutilisées, les mises à niveau de protocole et les transports proviennent tous d'un même endroit et évoluent de concert lorsque Chromium évolue.
Le compromis est franc. uTLS est plus léger et vous permet de concevoir toute salutation imaginable, tandis que chromenet apporte un auxiliaire de 25 Mo et vous offre le comportement de Chrome plutôt qu'un comportement personnalisé. Si vous recherchez une dépendance minimale et un contrôle total de la négociation initiale, uTLS reste un excellent choix.
Toute conception implique des compromis, et nous tenons à être transparents sur les limites de celle-ci. Embarquer un véritable moteur réseau de navigateur n'est pas anodin : chaque binaire du moteur pèse environ 25 Mo. Sous macOS, les binaires ne sont pas notariés. Et sous Linux, votre système doit disposer de glibc 2.31 ou d'une version plus récente. Si ces contraintes conviennent à votre environnement, vous bénéficiez d'un véritable réseau Chrome en remplaçant simplement un seul champ de transport.
Le projet est disponible à l'adresse github.com/gosuda/chromenet. Si vous connaissez ses projets frères de la famille open source gosuda, gosuda.org/hqq et gosuda.org/sqlite3, l'esprit vous sera familier : reprendre des outils puissants et imposants issus de l'univers logiciel plus large pour les intégrer naturellement au Go pur.
Donc, si vous vous tournez vers uTLS parce que vous avez besoin que votre programme Go se comporte comme un navigateur, essayez chromenet. Il peut constituer une bonne alternative à uTLS, en particulier lorsque vous avez besoin de plus que de simples requêtes HTTPS : HTTP/2, HTTP/3, WebSocket et WebTransport transitent tous par le même moteur Chrome, sans code de liaison de votre côté.