#10390 Vite Plugin: Headers returned in Websocket handshake/upgrade are ignored
Valid bug confirmed in code. Response headers from Worker WebSocket upgrade are ignored in websockets.ts. No fix in PRs/changelog. Reporter provided excellent reproduction.
Fix packages/vite-plugin-cloudflare/src/websockets.ts to forward response headers during WebSocket upgrade.
Analysis Report
Issue Review: cloudflare/workers-sdk#10390
Summary
WebSocket handshake/upgrade response headers from Workers are ignored by the Vite plugin - headers like Set-Cookie set in the 101 response are never sent to the browser.
Findings
- Created: 2025-08-17
- Updated: 2025-08-18
- Version: @cloudflare/vite-plugin ^1.11.5 → 1.21.2 (current)
- Component: vite-plugin-cloudflare (websockets.ts)
- Labels: bug, vite-plugin
- Comments: 0
Key Evidence
- Code inspection confirms the bug still exists: In
packages/vite-plugin-cloudflare/src/websockets.ts, thehandleWebSocketfunction extractsresponse.webSocketbut completely ignoresresponse.headers - No PRs fix this issue: Searched for PRs mentioning #10390 and websocket-related keywords - no fixes found
- No changelog entries: The vite-plugin-cloudflare CHANGELOG has no mentions of issue #10390 or websocket header fixes
- Recent commits don't address this: 5 commits since the issue was created, none relate to websocket headers
- Reporter provided excellent details: Reproduction repo, specific code reference, version info, and clear expected vs actual behavior
Root Cause Analysis
The bug is in packages/vite-plugin-cloudflare/src/websockets.ts at lines 37-51:
const response = await miniflare.dispatchFetch(url, {
headers,
method: request.method,
});
const workerWebSocket = response.webSocket;
if (!workerWebSocket) {
socket.destroy();
return;
}
nodeWebSocket.handleUpgrade(
request,
socket,
head,
async (clientWebSocket) => {
void coupleWebSocket(clientWebSocket, workerWebSocket);
nodeWebSocket.emit("connection", clientWebSocket, request);
}
);
Problem: The response.headers are never used. When the worker returns a 101 response with headers like Set-Cookie or custom headers, those headers should be included in the WebSocket upgrade response sent to the client. However, nodeWebSocket.handleUpgrade() doesn't automatically forward these headers.
Proposed Solution
The ws library's handleUpgrade doesn't directly support custom headers, but you can write headers to the socket before completing the upgrade. Here's a suggested fix:
nodeWebSocket.handleUpgrade(
request,
socket,
head,
async (clientWebSocket) => {
// Forward headers from the worker response to the client
// Note: Some headers should be excluded as they're handled by the upgrade
const excludedHeaders = new Set([
'connection',
'upgrade',
'sec-websocket-accept',
'sec-websocket-extensions',
'sec-websocket-protocol',
]);
// Write additional headers to the socket
// The ws library has already written the base 101 response headers
// We need to inject headers before the final \r\n
const extraHeaders: string[] = [];
for (const [key, value] of response.headers.entries()) {
if (!excludedHeaders.has(key.toLowerCase())) {
extraHeaders.push(`${key}: ${value}`);
}
}
if (extraHeaders.length > 0) {
// This approach won't work with handleUpgrade as-is
// Alternative: use completeUpgrade or manual upgrade handling
}
void coupleWebSocket(clientWebSocket, workerWebSocket);
nodeWebSocket.emit("connection", clientWebSocket, request);
}
);
Better approach: Use the ws library's lower-level API or implement custom upgrade handling similar to how Wrangler does it. Looking at how wrangler dev handles this would provide the correct pattern.
The fix likely requires:
- Not using
handleUpgradeand instead doing a manual WebSocket upgrade - Writing the HTTP 101 response with all headers from the Worker response
- Then establishing the WebSocket connection
Recommendation
Status: KEEP OPEN
Reasoning: This is a valid, reproducible bug with clear code evidence. The issue prevents developers from testing WebSocket authentication flows (Set-Cookie headers) in local development with the Vite plugin. The reporter provided a minimal reproduction and pinpointed the exact file/line causing the issue.
Action: This bug needs to be fixed in packages/vite-plugin-cloudflare/src/websockets.ts. Compare with Wrangler's WebSocket upgrade handling to ensure parity.
Implementation Details
Difficulty: Medium
- The fix requires understanding both the
wslibrary's API and the HTTP WebSocket upgrade protocol - Need to maintain compatibility with existing behavior while adding header forwarding
- Testing WebSocket upgrades with headers requires some setup
Files to Modify:
packages/vite-plugin-cloudflare/src/websockets.ts- main fix location
Testing Recommendations:
- Use the reporter's reproduction repo: https://github.com/cloudkite/websocket-handshake
- Add test cases for:
Set-Cookieheaders in WebSocket upgrade response- Custom headers (e.g.,
X-Custom-Header) - Verify excluded headers (Connection, Upgrade, etc.) are not duplicated
- Compare behavior with
wrangler devto ensure parity
Notes & Feedback (0)
No notes yet.