Skip to content

fix(realtime): stop reporting the gateway's own 1002 as the upstream's close code - #1339

Merged
jarvis9443 merged 2 commits into
mainfrom
fix/realtime-invalid-close-f22
Oct 21, 2026
Merged

jarvis9443 merged 2 commits into
mainfrom
fix/realtime-invalid-close-f22

Conversation

@jarvis9443

@jarvis9443 jarvis9443 commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

When an upstream closes /v1/realtime with a code that may not be sent in a Close frame (1004, 2999, ...), the client got Close 1002 "Protocol violation" and an error event saying upstream websocket closed with code 1002: Protocol violation. The upstream never sent 1002: tungstenite replaces any received Close whose code is not allowed with its own (1002, "Protocol violation") frame and drops the original code, and the relay forwarded that as if it were the upstream's.

The library gives no way to recover the original code, and a genuine upstream (1002, "Protocol violation") looks identical. So that exact frame is now treated as the library's replacement: the client gets 1011, and the server_error event says the upstream sent a close frame the gateway cannot relay — an invalid close code, or 1002 "Protocol violation". Any other legal code, including 1002 with a different reason, is still relayed as received.

The other upstream ends in the same relay also claimed codes the upstream never sent, and are fixed here too:

  • a Close with no status code said closed with code 1005; it now says the upstream closed without a status code;
  • a transport or protocol error (TCP reset, oversized control frame, ...) said closed with code 1006: upstream error; it now says upstream websocket connection failed: <error>, with the same cause chain the access log records;
  • a stream ending without any Close frame said closed with code 1006; it now says the connection ended without a close frame.

The client's close code (1011), the Close reason and the access-log status are unchanged for all three.

Tests: realtime-close-e2e gets a raw-frame mode in its mock upstream to send what ws refuses to (Close 1004 / 2999 and an oversized Close), plus assertions on the exact event message for the no-status, drop and protocol-error ends and a check that 1002 with its own reason is still relayed. Five of the cases fail on main and pass with this change. A unit test also drives tungstenite with a Close(1004) and asserts it yields exactly the frame the relay matches, so a library bump that changes the substitute fails in CI rather than silently reporting 1002 again.

🤖 Generated with Claude Code

…s close code

tungstenite replaces an upstream Close whose code may not be sent (1004,
2999, ...) with its own 1002 "Protocol violation" and drops the original
code, so the relay forwarded 1002 to the client and its error event said
the upstream had closed with 1002. Treat exactly that frame as the
library's replacement: the client gets 1011 and the event says the
upstream sent a close frame the gateway cannot relay (an invalid close
code, or 1002 "Protocol violation"). Any other legal code, 1002 with a
different reason included, is still relayed as received.

The sibling ends no longer claim codes the upstream never sent: a Close
without a status code, a transport or protocol error, and a stream that
ends without a Close each get an event describing what happened. The
client's close code (1011), its reason and the access-log status are
unchanged.
@coderabbitai

coderabbitai Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

  • Run on-demand review

This review includes 2 billable files and costs up to $0.50.

  • Ask an admin to make reviews automatic

Open in CodeRabbit

Reviews can continue after your included limit without a manual trigger. An admin must approve usage-based billing.

Or wait 38 minutes for your next included review.

Check out review usage here.

View limit details

Limit details: You’ve used all 2 included reviews currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Essentials
  • Run ID: 4a22f3da-7232-4591-8fcc-13019f94b752
📥 Commits

Reviewing files that changed from the base of the PR and between 7cd42f7 and 3567793.

📒 Files selected for processing: 2
  • crates/aisix-proxy/src/realtime.rs
  • tests/e2e/src/cases/realtime-close-e2e.test.ts
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

…t for event and log

A unit test drives tungstenite with a Close(1004) and asserts it yields
exactly LIBRARY_REJECTED_CLOSE, so a library bump that changes the
substitute fails here instead of silently reporting 1002 again. The
upstream-error event now carries the same cause chain as the access log,
and the drop e2e pins the transport-error path it actually takes.
@jarvis9443
jarvis9443 merged commit 889a093 into main Oct 21, 2026
20 checks passed
@jarvis9443
jarvis9443 deleted the fix/realtime-invalid-close-f22 branch October 21, 2026 12:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant