Skip to content

Proxy Kubernetes websocket streams that offer no subprotocol - #2832

Merged
Eugeny merged 5 commits into
mainfrom
2662-fixup
Oct 27, 2026
Merged

Eugeny merged 5 commits into
mainfrom
2662-fixup

Conversation

@Eugeny

@Eugeny Eugeny commented Oct 27, 2026

Copy link
Copy Markdown
Member

fixes for #2662

Description

Kubernetes websocket clients can omit Sec-WebSocket-Protocol, but the proxy currently requires it. Kubernetes can also return an empty protocol header, which reqwest-websocket rejects.

Accept an empty offer. A small adapter removes a single empty response protocol header only when no protocol was offered and the upstream returned HTTP 101. The library continues to validate the handshake and frame the connection.

Negotiate upstream before replying downstream, echo the API server's selected protocol, preserve stream audit timing, and forward rejected upgrades. Poem's callback consumes the upstream socket once through Mutex::into_inner.

This overlaps with #2663 in the websocket handler; the second PR to merge will need a rebase.

Validation

  • CI tests and both release builds passed on the updated commit.
  • All 27 Kubernetes Rust tests passed, including the handshake matrix, audit timing, and refusal forwarding checks.
  • The authenticated no-subprotocol websocket integration regression passed locally.
  • Full Warpgate build, scoped Clippy, rustfmt, and git diff --check passed. Clippy reports warnings in unchanged code.

AI Usage

  • Fully vibe coded
  • AI-designed, AI-coded, manually checked
  • Human-designed, AI-coded
  • Human-designed, human-coded (includes AI autocompletions and boilerplate gen)

fergusean and others added 5 commits October 26, 2026 18:55
…adapter

Allow exec/attach/port-forward clients to offer no subprotocol. Use the
reqwest-websocket public client and request-builder traits to normalize
only a single empty protocol response on 101 when no protocol was offered.
The library continues to construct and validate the handshake and handle
WebSocket frames through the existing authenticated HTTP/1.1 client.

Negotiate upstream before replying downstream so both sides acknowledge
the same selected protocol. Preserve started/rejected audit ordering and
forward the cluster's refusal response. Cover the compatibility case through
the full proxy, a compact protocol-boundary matrix, audit timing, and refusals.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Codex <codex@openai.com>
Use Mutex::into_inner for Poem’s FnOnce callback instead of an optional socket and a duplicate-consumption error. Keep the adapter’s handshake validation and shorten its helper comments.

Co-authored-by: Codex <codex@openai.com>
Trigger fresh PR checks after Docker Hub rate limits and timeouts stopped the previous runs. No source changes.

Co-authored-by: Codex <codex@openai.com>
@Eugeny
Eugeny merged commit ab83bb3 into main Oct 27, 2026
28 of 32 checks passed
@Eugeny
Eugeny deleted the 2662-fixup branch October 27, 2026 04:58
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.

2 participants