Skip to content

fix(proxy): prevent Responses WebSocket disconnects after handshake - #1516

Open
ROOOO wants to merge 1 commit into
ding113:devfrom
ROOOO:codex/ws-upgrade-routing
Open

ROOOO wants to merge 1 commit into
ding113:devfrom
ROOOO:codex/ws-upgrade-routing

Conversation

@ROOOO

@ROOOO ROOOO commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Responses WebSocket connections can close immediately after a successful 101 handshake when CCH and Next.js both handle the same upgrade event.

Route /v1/responses upgrades exclusively to CCH before ordinary upgrade listeners run. Preserve delegation of other upgrade paths, listener semantics, the private worker HTTP target, payload limits, and shutdown cleanup.

Validation: The standalone branch based on upstream v0.9.8 passed production build, Biome check and autofix, TypeScript checking, and the full Vitest suite in an isolated environment: 9,442 tests passed and 13 skipped, using a 30-second per-test timeout. Regression tests cover competing listener order, upgrade delegation, and forwarding to the private worker target.

RetriggerView in GreptileConfidence Score: 5/5

The PR appears safe to merge; no blocking issues were found.

Summary

The PR gives CCH sole ownership of /v1/responses WebSocket upgrades, preventing competing listeners from closing an accepted connection.

  • Responses WebSocket upgrades reach their handler before other listeners.

No actionable issues were found. No tests were run during this review.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[HTTP upgrade] --> B{Responses path?}
  B -->|Yes| C{WebSocket support available?}
  C -->|Yes| D[CCH handles upgrade exclusively]
  C -->|No| E[Destroy socket]
  B -->|No| F{Other upgrade listeners?}
  F -->|Yes| G[Call original emitter]
  F -->|No| E
Loading

Reviews (3) · Last reviewed commit: "fix(proxy): prevent Responses WebSocket ..." · Reviewed by Greptile

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ⚠️ Failed 2026-10-27T18:48:25.303824Z
We couldn’t complete this review. Comment @codex review to try again.
35e5c2a New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@coderabbitai

coderabbitai Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review.

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 960f6218-24e6-4968-99a4-673b35daf53e
📥 Commits

Reviewing files that changed from the base of the PR and between 8d6ddae and b38b2bd.

📒 Files selected for processing: 4
  • docs/downstream-changes.md
  • server.js
  • src/app/v1/_lib/responses-ws/__tests__/server-helpers.test.ts
  • tests/unit/server-ws-upgrade-routing.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 7 remain after this review.

Walkthrough

该变更新增 /v1/responses WebSocket 升级路由。目标路径由专用处理器接管,其他升级请求交给普通监听器;无监听器时关闭连接。新增路由、错误处理和请求转发测试,并记录下游差异。

Changes: Responses WebSocket 升级路由

层 / 文件 摘要
安装升级分发器并识别目标路径
server.js, src/app/v1/_lib/responses-ws/__tests__/server-helpers.test.ts, docs/downstream-changes.md
installResponsesWsUpgradeHandler 按路径分发升级请求。/v1/responses 交由 WebSocket 处理器;其他路径交给普通升级监听器,无监听器时销毁 socket。main 改为安装该分发器。辅助函数测试覆盖精确路径和拒绝路径;下游差异文档记录了该行为和维护规则。
验证升级路由及请求转发行为
tests/unit/server-ws-upgrade-routing.test.ts
新增 socket 级测试,覆盖竞争监听器注册顺序、非目标路径委派、缺少 WebSocket 实现、异常处理、普通事件行为,以及 response.create 请求转发至指定私有 HTTP 目标。

Priority: Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Suggested reviewers: ding113

Merge Risk: Minimal · up to b38b2

The upgrade-routing change is ready to merge after normal checks.

Pre-merge checks: Passed 4
Check name Status Explanation
Title check Passed 标题明确描述了修复 Responses WebSocket 握手后断开的问题,与变更的主要目标一致。
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Description check Passed PR 描述明确说明了 /v1/responses WebSocket 升级路由问题、实现目标、兼容行为和验证结果,与代码变更及测试内容直接相关。
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the size/M Medium PR (< 500 lines) label Oct 22, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Summary

No significant issues identified in this PR. The refactoring cleanly extracts the WebSocket upgrade handler into a testable installResponsesWsUpgradeHandler function, solves the competing-listener race with a well-designed emit-level dispatcher, and includes comprehensive regression tests covering all routing scenarios.

PR Size: M

  • Lines changed: 492 (457 additions, 35 deletions)
  • Files changed: 4

Review Coverage

  • Logic and correctness - Clean
  • Security (OWASP Top 10) - Clean
  • Error handling - Clean
  • Type safety - Clean (JS file; test types are correct)
  • Documentation accuracy - Clean
  • Test coverage - Thorough (8 test cases covering competing listeners, delegation, rejection, error paths, and end-to-end forwarding)
  • Code clarity - Good

Automated review by Claude AI

Symptoms:
Responses WebSocket connections can close immediately after a successful
101 handshake, causing clients to report "Connection reset without closing
handshake" and repeatedly reconnect. Different worker initialization orders
can produce alternating successful and failed connections.

Cause:
CCH and Next.js can both handle the same WebSocket upgrade event. After CCH
completes the handshake, the Next.js listener can close the accepted socket.

Solution:
Route /v1/responses upgrades exclusively to CCH before invoking ordinary
upgrade listeners. Preserve listener dispatch for other paths, the current
worker's private HTTP loopback target, payload limits, and cleanup behavior.
@ROOOO
ROOOO force-pushed the codex/ws-upgrade-routing branch from d63ba84 to 35e5c2a Compare October 27, 2026 18:47

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:core bug Something isn't working size/M Medium PR (< 500 lines)

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

1 participant