Steven
Steven4 min čtení

Přepis naživo, když firewall blokuje WebSockety

Firemní sítě milují povolit HTTPS a tiše zabít WebSocket upgrady. To potichu rozbíjí přepis v reálném čase. GeekBye v2.0.8 automaticky přejde na čistě HTTPS transport — a jeho vydání odhalilo bug, který by celou funkci učinil zbytečnou.

Přepis
Sítě
Engineering
Vydání GeekBye
Přepis naživo, když firewall blokuje WebSockety

Existuje jeden konkrétní, k šílenství dohánějící způsob, jak přepis v reálném čase selže na firemní síti. Tvoje Wi-Fi je v pořádku. HTTPS funguje — načteš jakýkoli web. Ale přepis naživo prostě... nenastartuje, a nic ti neřekne proč.

Viníkem je třída firemních proxy, které povolí běžný HTTPS provoz, ale blokují WebSocket upgrade — handshake, který mění HTTPS připojení na trvalý, obousměrný kanál, jaký přepis v reálném čase potřebuje. Pro proxy vypadá WebSocket jako nemonitorovaný tunel ven ze sítě, takže ho zabije. Pro tebe je přepis potichu rozbitý.

GeekBye v2.0.8 přidal automatický fallback přesně pro tohle — a jeho stavba vyhrabala bug, který by způsobil, že by celá funkce nedělala nic.

Proč fallback, ne jen retry

Nestabilní sítě už řešíme. Když ti připojení spadne uprostřed session, GeekBye se s backoffem znovu připojí a bufferuje tvé audio, takže se nic neztratí — to je samostatná funkce popsaná v proč se váš AI zapisovatel zastaví při špatném Wi-Fi.

Ale blokovaný WebSocket není nestabilní připojení. Opětovné zkoušení stejného WebSocketu proti proxy, které WebSockety odmítá, selhává pokaždé stejně, navždy. Jediným řešením je jiný transport — takový, který vypadá jako obyčejné HTTPS, jež proxy už povoluje.

Takže v2.0.8 přejde na čistě HTTPS transport přes stejný autentizovaný endpoint:

  • Dolů (přepisy vracející se k tobě): server-sent events — dlouhotrvající HTTPS odpověď, kterou proxy vidí jako běžné streamované stahování.
  • Nahoru (tvé odcházející audio): dávkované POST požadavky, každý nesoucí kus audia s pořadovým číslem, aby je server mohl znovu složit ve správném pořadí, i když je síť přehází.

Žádný trvalý socket, nic, co vypadá jako tunel — jen HTTPS požadavky a odpovědi. Pokud ti proxy dovolí použít web, dovolí i tohle.

Bug, který by vydal mrtvou funkci

Tady je ta část, která stojí za přečtení. Fallback se má spustit, když WebSocket připojení vyčerpá své pokusy se signaturou blokovaného transportu — každý pokus selže na upgradu, žádný problém s auth ani quotou, alespoň jedno odmítnutí ve tvaru proxy. Proxy blokující WebSocket obvykle odpoví na upgrade s HTTP 403 Forbidden nebo 407.

Problém: náš kód připojení už měl pravidlo, že 403 znamená fatální chybu autentizace — zastav, zobraz ji uživateli, nezkoušej znovu. Což je téměř všude správně. Ale znamenalo to, že 403 od blokujícího proxy — přesně ten signál, který měl spustit fallback — se místo toho vyhazovala jako fatální chyba dřív, než logika fallbacku vůbec mohla proběhnout. Jen ryzí pád připojení (uzavření 1006) propadl až k fallbacku. Takže funkce by fungovala pro vzácný případ a potichu selhala pro svůj skutečný hlavní cíl: firemní proxy.

Chytili jsme to při kalení vydání, ne v produkci. Oprava: 403/407 na upgrade větvi WebSocketu se nyní považuje za zotavitelnou, aby se smyčka připojení mohla vyčerpat do fallbacku — zatímco skutečné selhání autentizace (které přichází jinak, poté co upgrade uspěje) stále selhává rychle, přesně jako dřív. Regresní test nyní ukotvuje ten rozdíl: 403 od blokujícího proxy musí přejít na fallback; skutečná auth 403 nesmí.

Zbytek kalení šel po téže paranoidní linii: timeout na každém POSTu nahoru, aby proxy, které požadavek přijme, ale nikdy neodpoví, nemohlo zaseknout audio stream, a záruka, že skutečný problém s přihlášením nemůže být nikdy potichu zamaskován mechanikou fallbacku.

Testovali jsme to proti reálnému nepřátelskému proxy

Funkci, jejímž celým smyslem je přežití nepřátelských sítí, nelze validovat pouze unit testy — unit testy nemají proxy. Než jsme ji zapnuli, prohnali jsme skutečnou aplikaci lokálním reverse proxy nakonfigurovaným, aby dělal přesně to, co firemní proxy dělají: přeposílá HTTPS, odmítá WebSocket upgrady s 403.

Stopa v logu je stvrzenka: čtyři blokované WebSocket pokusy, rozpoznaná signatura vyčerpání, automatické přepnutí na HTTPS transport a poté zdravá 96sekundová session přepisu přes čisté HTTPS — 66 transkript segmentů, nula výpadků. Failover funguje, protože jsme ho sledovali, jak přepíná.

Tři přenositelná ponaučení

  1. „Funguje na nestabilním Wi-Fi" a „funguje za nepřátelským proxy" jsou různé záruky. Jedno potřebuje opětovné připojení; druhé potřebuje jiný transport. Jejich směšování nechává celou populaci firemních uživatelů potichu rozbitou.
  2. Tvoje klasifikace chyb může skrýt tvou vlastní funkci sama před sebou. Pravidlo, které je správné v 99 % případů (403 = fatální auth), bylo přesně špatné pro ta 1 %, kvůli kterým tato funkce existovala. Když přidáváš fallback, prověř, zda spouštěcí podmínka může fallback vůbec dosáhnout.
  3. Testuj protivníka, ne jen šťastnou cestu. Jediný poctivý test na „přežije proxy blokující WebSockety" je proxy blokující WebSockety. Postavili jsme jedno.

GeekBye v2.0.8 vydal HTTPS fallback za flagem a ověřený. K práci na spolehlivosti, vedle níž stojí, viz proč se váš AI zapisovatel zastaví při špatném Wi-Fi, a k sousedním vydáním z této série proč váš AI zapisovatel přestane nahrávat uprostřed meetingu (v2.0.9) a proč AI přepis komolí technické termíny (v2.0.11).