Skip to content

fix(websocket): capture upgrade request and pass wrapped socket to lifecycle hooks#207

Open
nicoske wants to merge 1 commit into
FOSSFORGE:mainfrom
nicoske:fix-ws-handshake-and-wrapped-socket-hooks
Open

fix(websocket): capture upgrade request and pass wrapped socket to lifecycle hooks#207
nicoske wants to merge 1 commit into
FOSSFORGE:mainfrom
nicoske:fix-ws-handshake-and-wrapped-socket-hooks

Conversation

@nicoske

@nicoske nicoske commented Jul 22, 2026

Copy link
Copy Markdown

Fixes #205

Two changes in the WebSocket adapter:

  • an upgrade handler now copies the upgrade request (path, query string, headers) before uWS invalidates it, and the adapter exposes it as socket.handshake with the parsed query and the remote address
  • lifecycle hooks receive the wrapped UwsSocket instead of the raw uWS socket, so client.data set in handleConnection is the same data the message handlers see, and the documented API (emit, join, ...) actually works inside the hooks. The disconnect hook gets the same instance, grabbed before the socket maps are cleaned up.

This is what the Lifecycle.md examples already describe, including the one that calls client.emit() inside handleConnection.

The handshake is set only on the wrapped socket on purpose. The raw socket also flows into the Nest websockets controller callback, and putting connection state there as well would invite the two paths to drift apart again.

New e2e suite (test/websocket/gateway-lifecycle.e2e.spec.ts) runs a real server with the built-in WebSocket client and covers: handshake url/query/headers/address, emit from handleConnection, data continuity between hook and handler, and instance identity across connect/message/disconnect.

Lint, unit (975) and e2e (238) suites are green on Node 24. No existing test needed changes.

Summary by CodeRabbit

  • New Features

    • WebSocket connections now expose handshake details, including URL, query parameters, headers, and remote address.
    • Connection and disconnection lifecycle callbacks receive the connected socket, enabling socket actions such as sending messages and accessing connection data.
  • Bug Fixes

    • Improved consistency by ensuring lifecycle handlers and message handlers reference the same socket instance.

…fecycle hooks

The adapter never installed an upgrade handler, so the HTTP upgrade
request (path, query string, headers) was thrown away and there was no
way for a gateway to read auth tokens or client metadata from the
connection. handleConnection/handleDisconnect also received the raw
uWS socket while message handlers get the wrapped UwsSocket, so data
attached during handleConnection was invisible to handlers and the
documented UwsSocket API (emit, join, data) crashed inside lifecycle
hooks.

Capture the upgrade request in an upgrade handler, expose it as
socket.handshake (url, parsed query, headers, remote address), and hand
the same wrapped socket instance to lifecycle hooks and message
handlers. Matches the Lifecycle.md examples, which already type the
hook parameter as UwsSocket and call client.emit() in handleConnection.
@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 08f4c18e-88bb-4b62-86ca-d0dd33a1771c

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • ✅ Review completed - (🔄 Check again to review again)
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
test/websocket/gateway-lifecycle.e2e.spec.ts (1)

100-107: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Use the shared ephemeral-port helper instead of a hardcoded port.

const port = 13390 binds the test server to a fixed port, risking collisions with other e2e spec files or parallel CI workers.

Based on learnings, uWS e2e tests should use the shared helper (test/helpers/get-port.ts, e.g. startAppOnEphemeralPort()) for ephemeral port allocation rather than a fixed port or server.address().port, to keep port-allocation logic consistent across e2e/spec files.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/websocket/gateway-lifecycle.e2e.spec.ts` around lines 100 - 107, The
websocket lifecycle test currently uses the hardcoded port constant 13390;
replace it with the shared ephemeral-port helper, such as
startAppOnEphemeralPort from get-port.ts. Update the beforeEach setup around
UwsAdapter.create and any dependent port usage to use the helper’s allocated
port while preserving the existing test lifecycle behavior.

Source: Learnings

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@test/websocket/gateway-lifecycle.e2e.spec.ts`:
- Around line 100-107: The websocket lifecycle test currently uses the hardcoded
port constant 13390; replace it with the shared ephemeral-port helper, such as
startAppOnEphemeralPort from get-port.ts. Update the beforeEach setup around
UwsAdapter.create and any dependent port usage to use the helper’s allocated
port while preserving the existing test lifecycle behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 66d18584-6197-4763-bbdf-bc9d32292bf2

📥 Commits

Reviewing files that changed from the base of the PR and between 6b80b10 and 5022eeb.

📒 Files selected for processing (4)
  • src/websocket/adapter/uws.adapter.ts
  • src/websocket/core/socket.ts
  • src/websocket/interfaces/uws-socket.interface.ts
  • test/websocket/gateway-lifecycle.e2e.spec.ts

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.

WebSocket gateways never see the upgrade request, and lifecycle hooks get the raw uWS socket

1 participant