fix: answer WebSocket upgrades with a clean 426 so Codex falls back to HTTP immediately (#2) - #169
Conversation
…s back to HTTP immediately (#2)
…ient history grows (#2)
…client abort
- The handle() `upgrade === "websocket"` 426 check is unreachable once the
dedicated 'upgrade' listener is registered: Node routes upgrade requests
to 'upgrade' and never to the request handler. Verified on both the plain
path and the MITM-decrypted (bili codex) path. Replace with a pointer comment.
- Add socket.on("error") to the 'upgrade' handler so a client vanishing
mid-426-write cannot surface as an uncaught ECONNRESET.
Full suite 456/456, typecheck + build clean.
|
LGTM on the core fix — and this one fixes a real, subtle bug, not a style issue. Why the old code was dead: the 426 rejection lived in the The raw-socket write is correct: valid HTTP/1.1 response, One scope note (non-blocking): this PR also bundles a 212-line Merge. |
Problem
Fixes #2 (codex 版本可能因为默认 socket 模式卡顿, 十几秒自动切 http 恢复).
New Codex versions default to Responses-over-WebSocket (
supports_websockets=true). In codex source (codex-rs/core/src/client.rs), only an HTTP 426 on the WS handshake triggers immediate fallback to HTTP POST; any other failure (e.g. socket destroyed with no response) goes through retry/backoff budgets first — that's the 10-20s stall users see before it auto-recovers on HTTP.bili already wrote a 426 inside its request handler, but the HTTP server never registered an
'upgrade'event listener, so Node's handling of upgrade requests is version-dependent — often the socket is destroyed without any response, pushing Codex onto the slow path.Fix
src/server.ts: explicitserver.on("upgrade")handler — always answers426 Upgrade Required+Connection: closewith a JSON error body and closes the socket immediately. Consistent on every Node version; Codex receiving 426 switches to HTTP POST in the same turn.bili codexmode: chatgpt.com / api.openai.com), since those land on the same server object.Tests
tests/ws-upgrade.test.ts: 426 + immediate close verified on both the plain path and the full CONNECT → TLS → upgrade MITM path.npm run typecheck✓, full suite 455/455 ✓,npm run build✓.Note:
src/update.tsuntouched — no no-op validation release needed; standard §5 release flow after merge.