Ensinando Seu Programa Go a Falar Como o Chrome

Se você já viajou para o exterior e pediu um café com uma frase perfeita de livro didático, conhece o olhar que o barista lhe dá. Sua gramática está correta. Cada palavra está no dicionário. Ainda assim, em menos de meio segundo, todos no café percebem que você é de fora da cidade.
O cliente HTTP padrão do Go tem um pouco desse problema. Ele é um ótimo padrão: confiável, limpo e pronto para trabalho sério logo de início. Quando seu programa se conecta a um servidor, no entanto, ele inconfundivelmente parece um programa Go. Na maioria das vezes, ninguém se importa. Ainda assim, alguns sites, CDNs e configurações de teste prestam muita atenção a quem está batendo à porta e se comportam de maneira bem diferente dependendo do tipo de cliente que acreditam estar recebendo.
É por isso que construímos o gosuda.org/chromenet. Em vez de ensinar o cliente padrão do Go a fazer uma imitação razoável de navegador, o chromenet permite que um programa Go se comunique com a web usando o mesmo motor de rede que o Google Chrome utiliza, ou seja, o próprio código de rede do Chromium. Seja para verificar como suas configurações de teste tratam o tráfego de navegadores, seja para se comunicar com um site protegido por uma CDN exigente, falar pelo motor do Chrome elimina uma camada inteira de incertezas.
Você não precisa reescrever sua aplicação para usá-lo. No seu código, ele funciona como um substituto direto (drop-in) para o http.Transport. Você continua usando o http.Client da forma de sempre, e o chromenet cuida da comunicação por baixo.
Para experimentar a versão mais recente, instale-a com o go get:
1go get gosuda.org/chromenet@v0.2.10157081033800
Em seguida, atribua o seu transporte ao cliente:
1client := http.Client{
2 Transport: chromenet.NewTransport(chromenet.Options{}),
3}
Com esta versão, toda a gama de tráfego web moderno passa pelo motor do Chrome. Agora ele abrange requisições web comuns, WebSocket e WebTransport. As versões anteriores só tratavam adequadamente as requisições comuns, enquanto WebSocket e WebTransport eram substitutos provisórios. Isso significava que sua saudação inicial à porta soava como o Chrome, mas, se você mudasse para outro estilo de conversa, sua farsa podia ser descoberta. Esta versão substitui esses substitutos pelas implementações reais.
Espere, se estamos usando o próprio código de rede do Chromium, isso significa que sua compilação Go enxuta vira uma dor de cabeça com um compilador C enorme? Felizmente, não. Seu código Go continua sendo Go puro, sem cgo e sem necessidade de um compilador C.
Em vez de incorporar o código do navegador diretamente no seu binário, o chromenet executa o motor como um pequeno programa separado ao lado do seu programa Go. Pense nisso como contratar um intérprete local fluente que caminha ao seu lado, em vez de tentar reconstruir suas próprias cordas vocais. Como o motor roda nesse programa separado, uma falha dentro dele não derruba o seu serviço.

Seu programa Go continua sendo Go puro enquanto um pequeno programa auxiliar encaminha o tráfego pelo motor de rede do Chromium.
Também não há nada extra para instalar na sua estação de trabalho ou nos seus servidores. Os binários do motor para Linux, macOS e Windows, em arquiteturas Intel/AMD e ARM, são distribuídos dentro do próprio módulo Go e são verificados antes de serem executados.
Distribuir binários dentro de um módulo levanta, compreensivelmente, uma questão para quem se preocupa com confiança, e queríamos uma resposta direta. Os binários são construídos de forma reprodutível a partir de uma versão específica do Chromium, atualmente o Chromium 157, de modo que qualquer pessoa pode recompilá-los e obter exatamente os mesmos bytes, e cada versão é atestada pelo GitHub. Para acompanhar o mundo dos navegadores sem trabalho manual, uma tarefa agendada segue o canal estável do Chromium e atualiza a versão automaticamente quando um novo Chrome é lançado.
E quanto ao uTLS?
Se você já tentou fazer um cliente Go parecer um navegador, provavelmente conheceu o uTLS. É um belo trabalho: uma biblioteca Go que permite vestir a primeira mensagem de uma conexão segura para que se assemelhe ao Chrome, ao Firefox ou ao que você preferir. É pequena, é Go puro e nada extra roda ao lado do seu programa.
O problema está em até onde vai a fantasia. O uTLS cobre o handshake, que são as primeiras palavras da conversa. Todo o restante ainda cabe a você construir: a camada HTTP/2 precisa ser conectada e ajustada manualmente, o HTTP/3 é uma aventura à parte, e WebSocket ou WebTransport exigem ainda mais cola de código. Além disso, os perfis do Chrome são cópias, então alguém precisa mantê-los atualizados sempre que o Chrome muda seus hábitos. É um pouco como imitar o sotaque de uma pessoa enquanto o resto da sua linguagem corporal ainda a denuncia.
O chromenet segue o caminho oposto. Ele não imita o Chrome, ele pede ao próprio motor do Chrome que faça a comunicação, de modo que o handshake, a forma como as conexões são reutilizadas, as atualizações de protocolo e os transportes vêm de um único lugar e evoluem juntos quando o Chromium evolui.
A troca é honesta. O uTLS é mais leve e permite criar qualquer saudação que você imaginar, enquanto o chromenet traz um auxiliar de 25 MB e oferece o comportamento do Chrome em vez de um comportamento personalizado. Se você quer uma dependência minúscula e controle total do handshake, o uTLS continua sendo uma ótima escolha.
Todo design envolve compromissos, e queremos ser francos sobre os limites aqui. Empacotar um motor de rede de navegador real não é algo pequeno: cada binário do motor tem cerca de 25 MB. No macOS, os binários não são notarizados. E no Linux, seu sistema precisa do glibc 2.31 ou mais recente. Se esses limites funcionam para a sua configuração, você obtém a rede real do Chrome trocando um único campo de transporte.
O projeto está em github.com/gosuda/chromenet. Se você conhece seus projetos irmãos da família open source gosuda, gosuda.org/hqq e gosuda.org/sqlite3, o espírito será familiar: pegar máquinas capazes e pesadas do vasto mundo do software e fazê-las se sentir em casa em Go puro.
Portanto, se você recorre ao uTLS porque precisa que seu programa Go soe como um navegador, experimente o chromenet. Ele pode ser uma boa alternativa ao uTLS, especialmente quando você precisa de mais do que requisições HTTPS: HTTP/2, HTTP/3, WebSocket e WebTransport passam pelo mesmo motor do Chrome, sem código de cola do seu lado.