GoSuda

At lære dit Go-program at tale som Chrome

By Lemon Mint views ...

Hvis du nogensinde har rejst til udlandet og bestilt kaffe med en frase, der var fejlfri efter lærebogen, kender du det blik, baristaen giver dig. Din grammatik er i orden. Hvert ord findes i ordbogen. Og alligevel ved alle i caféen inden for et halvt sekund, at du kommer udefra.

Go's standardklient til HTTP har lidt af det samme problem. Den er en fremragende standard: pålidelig, ren og klar til seriøst arbejde lige fra start. Når dit program dog henvender sig til en server, ser det utvetydigt ud som et Go-program. Det generer som regel ingen. Alligevel er der nogle websteder, CDN'er og testopsætninger, som er meget opmærksomme på, hvem der banker på døren, og de opfører sig ganske forskelligt afhængigt af, hvilken type klient de tror, de taler med.

Det er derfor, vi har bygget gosuda.org/chromenet. I stedet for at lære Go's standardklient at efterligne en browser på en acceptabel måde, lader chromenet et Go-program kommunikere med nettet via den samme netværksmotor, som Google Chrome bruger, nemlig Chromiums egen netværkskode. Uanset om du undersøger, hvordan dine egne testopsætninger behandler browsertrafik, eller taler med et websted bag en kræsen CDN, fjerner det at tale via Chromes motor et helt lag af gætteri.

Du behøver ikke omskrive din applikation for at bruge det. I din kode fungerer det som en direkte erstatning for http.Transport. Du bruger fortsat http.Client, som du altid har gjort, og chromenet håndterer samtalen under overfladen.

For at prøve den seneste udgave installerer du den med go get:

1go get gosuda.org/chromenet@v0.2.10157081033800

Giv derefter dens transport til din klient:

1client := http.Client{
2	Transport: chromenet.NewTransport(chromenet.Options{}),
3}

Med denne udgave passerer hele spektret af moderne webtrafik gennem Chromes motor. Det dækker nu almindelige webforespørgsler, WebSocket og WebTransport. Tidligere versioner håndterede kun almindelige forespørgsler ordentligt, mens WebSocket og WebTransport var stedfortrædere. Det betød, at din første hilsen ved hoveddøren lød som Chrome, men hvis du skiftede til en anden form for samtale, kunne din dække glide. Denne udgave erstatter disse stedfortrædere med det rigtige.

Men hvis vi bruger Chromiums egen netværkskode, betyder det så, at dit stille Go-build bliver til en omfattende C-compiler-hovedpine? Heldigvis ikke. Din Go-kode forbliver almindelig Go, uden cgo og uden behov for en C-compiler.

I stedet for at svejse browserkode direkte ind i din binære fil, kører chromenet motoren som et lille, separat program ved siden af dit Go-program. Tænk på det som at ansætte en flydende lokal tolk, der går ved din side, i stedet for at forsøge at genopbygge dine egne stemmebånd. Fordi motoren kører i det separate program, kan et nedbrud i den ikke få din tjeneste til at gå ned.

Sådan fungerer chromenet: dit Go-program spørger et lille hjælpeprogram, som kører Chromiums netværksmotor og taler med nettet

Dit Go-program forbliver almindelig Go, mens et lille hjælpeprogram fører trafikken gennem Chromiums netværksmotor.

Der er heller ikke noget ekstra at installere på din arbejdscomputer eller dine servere. Motorens binærfiler til Linux, macOS og Windows, på både Intel/AMD og ARM, leveres direkte i Go-modulet og verificeres, før de køres.

At levere binærfiler i et modul rejser forståeligt nok et spørgsmål for enhver, der er optaget af tillid, og vi ønskede et ligetil svar. Binærfilerne er bygget på en reproducerbar måde ud fra en bestemt Chromium-udgave, aktuelt Chromium 157, så enhver kan genopbygge dem og få præcis de samme bytes, og hver udgave attesteres af GitHub. For at følge med i browserverdenen uden manuelt arbejde følger et planlagt job Chromiums stabile kanal og opdaterer versionen automatisk, når en ny Chrome udgives.

Hvad med uTLS?

Hvis du tidligere har forsøgt at få en Go-klient til at ligne en browser, er du sandsynligvis stødt på uTLS. Det er et smukt stykke arbejde: et Go-bibliotek, der lader dig klæde den allerførste besked i en sikker forbindelse ud, så den ligner Chrome, Firefox eller hvad du end ønsker. Det er lille, det er rent Go, og intet ekstra kører ved siden af dit program.

Det afgørende er, hvor langt kostumet rækker. uTLS dækker håndtrykket, som er de første få ord i samtalen. Alt derefter må du stadig bygge selv: HTTP/2-laget skal tilsluttes og finjusteres manuelt, HTTP/3 er et separat eventyr, og WebSocket eller WebTransport kræver endnu mere lim. Chrome-forudindstillingerne er desuden kopier, så nogen skal holde dem opdaterede, hver gang Chrome ændrer sine vaner. Det minder lidt om at efterligne en persons accent, mens resten af kropssproget stadig røber en.

chromenet vælger den modsatte vej. Det efterligner ikke Chrome, men lader Chromes egen motor styre samtalen, så håndtrykket, måden forbindelser genbruges på, protokoldgraderingerne og transporterne alle kommer fra ét sted og bevæger sig sammen, når Chromium bevæger sig.

Afvejningen er ærlig. uTLS er lettere og lader dig udforme enhver hilsen, du kan forestille dig, mens chromenet medbringer en hjælper på 25 MB og giver dig Chromes adfærd i stedet for en tilpasset. Hvis du ønsker en lille afhængighed og fuld kontrol over håndtrykket, er uTLS stadig et fremragende valg.

Ethvert design har afvejninger, og vi ønsker at være åbne om grænserne her. At pakke en rigtig browsers netværksmotor ind er ikke lille: hver motorbinær fil fylder omkring 25 MB. På macOS er binærfilerne ikke notariserede. Og på Linux skal dit system have glibc 2.31 eller nyere. Hvis disse grænser passer til din opsætning, får du rigtig Chrome-netværkskommunikation ved blot at udskifte et enkelt transportfelt.

Projektet findes på github.com/gosuda/chromenet. Hvis du kender dets søsterprojekter i gosuda open source-familien, gosuda.org/hqq og gosuda.org/sqlite3, vil ånden være genkendelig: at tage kapable, tunge værktøjer fra den bredere softwareverden og gøre dem hjemmevante i almindelig Go.

Så hvis du griber efter uTLS, fordi dit Go-program skal lyde som en browser, så prøv chromenet. Det kan være et godt alternativ til uTLS, især når du har brug for mere end HTTPS-forespørgsler: HTTP/2, HTTP/3, WebSocket og WebTransport kører alle gennem den samme Chrome-motor, uden lim-kode fra din side.