Skip to content

WebSocket request/response headers#4166

Merged
chrmarti merged 1 commit intomainfrom
chrmarti/cherry-pick-websocket-headers
Mar 3, 2026
Merged

WebSocket request/response headers#4166
chrmarti merged 1 commit intomainfrom
chrmarti/cherry-pick-websocket-headers

Conversation

@chrmarti
Copy link
Collaborator

@chrmarti chrmarti commented Mar 3, 2026

Cherry-picking #4160

@chrmarti chrmarti self-assigned this Mar 3, 2026
@chrmarti chrmarti marked this pull request as ready for review March 3, 2026 21:12
Copilot AI review requested due to automatic review settings March 3, 2026 21:12
@chrmarti chrmarti enabled auto-merge March 3, 2026 21:12
@vs-code-engineering vs-code-engineering bot added this to the 1.111.0 milestone Mar 3, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR cherry-picks changes from PR #4160 to add WebSocket request/response header support. It enables WebSocket connections to send full authentication and intent headers (matching the HTTP path), captures response headers from the HTTP upgrade handshake, and propagates request IDs to telemetry events.

Changes:

  • Introduces HeadersImpl (a reusable IHeaders implementation), WebSocketConnection, and WebSocketConnectOptions types; adds createWebSocket to the IFetcherService interface
  • Replaces the ad-hoc secret key parameter in WebSocket connection creation with a flexible headers map, and captures server response headers via a monkey-patched undici agent
  • Extends all WebSocket telemetry events with requestId and gitHubRequestId fields from the handshake response headers

Reviewed changes

Copilot reviewed 14 out of 16 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/platform/networking/common/fetcherService.ts Adds HeadersImpl, WebSocketConnection, WebSocketConnectOptions and createWebSocket to IFetcherService
src/platform/networking/vscode-node/fetcherServiceImpl.ts Implements createWebSocket using undici to intercept HTTP 101 response headers
src/platform/networking/node/chatWebSocketManager.ts Refactors connection creation to use headers map; exposes responseHeaders on connections
src/platform/networking/node/chatWebSocketTelemetry.ts Adds requestId/gitHubRequestId to all WebSocket telemetry events
src/platform/networking/node/nodeFetcher.ts Replaces inline anonymous IHeaders implementation with new HeadersImpl
src/platform/networking/node/test/nodeFetcherService.ts Adds stub createWebSocket to implement updated interface
src/extension/prompt/node/chatMLFetcher.ts Builds and passes full header set to WebSocket connection; reads response x-request-id
src/lib/node/chatLibMain.ts Stub createWebSocket in SingleFetcherService
src/platform/networking/test/node/networking.spec.ts Stub createWebSocket in test fetcher
src/platform/endpoint/node/test/routerDecisionFetcher.spec.ts Stub createWebSocket in test fetcher
src/platform/authentication/test/node/copilotToken.spec.ts Stub createWebSocket in test fetcher
src/extension/mcp/test/vscode-node/util.ts Stub createWebSocket in fixture fetcher
package.json / package-lock.json / chat-lib/package.json / chat-lib/package-lock.json Bumps @vscode/copilot-api from 0.2.13 to 0.2.15
Files not reviewed (1)
  • chat-lib/package-lock.json: Language not supported
Comments suppressed due to low confidence (1)

src/platform/networking/node/chatWebSocketManager.ts:304

  • In the onClose handler during the connection setup phase (the close-before-open scenario), this._responseHeaders is not updated from connection.responseHeaders before calling the telemetry sender. By contrast, the onError handler does update this._responseHeaders = connection.responseHeaders before accessing this._requestId and this._gitHubRequestId. If the server sends response headers before closing (e.g., in an HTTP 401/403 upgrade rejection), those headers won't be available in the closeDuringSetup telemetry. The fix is to add this._responseHeaders = connection.responseHeaders; at the beginning of the onClose handler in the setup phase, just like it's done in onError.
			const onClose = (event: CloseEvent) => {
				cleanup();
				this._state = ConnectionState.Closed;
				const connectDurationMs = Date.now() - (this._connectStartTime ?? Date.now());
				const closeCodeDescription = wsCloseCodeToString(event.code);
				this._logService.debug(`[ChatWebSocketManager] Connection closed during setup for conversation ${this._conversationId} turn ${this._turnId} (code: ${event.code} ${closeCodeDescription}, reason: ${event.reason || '<empty>'}, wasClean: ${event.wasClean})`);
				ChatWebSocketTelemetrySender.sendCloseDuringSetupTelemetry(this._telemetryService, {
					conversationId: this._conversationId,
					turnId: this._turnId,
					requestId: this._requestId,
					gitHubRequestId: this._gitHubRequestId,
					closeCode: event.code,
					closeReason: closeCodeDescription,
					closeEventReason: event.reason,
					closeEventWasClean: String(event.wasClean),
					connectDurationMs,
				});
				reject(new Error('WebSocket closed during connection setup'));

@chrmarti chrmarti added this pull request to the merge queue Mar 3, 2026
Merged via the queue into main with commit 95a0ce8 Mar 3, 2026
22 of 23 checks passed
@chrmarti chrmarti deleted the chrmarti/cherry-pick-websocket-headers branch March 3, 2026 21:40
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.

3 participants