diff --git a/src/shared/signalr/connection.ts b/src/shared/signalr/connection.ts index 0ef3faff..ddfc49ba 100644 --- a/src/shared/signalr/connection.ts +++ b/src/shared/signalr/connection.ts @@ -224,6 +224,8 @@ export function _resetSharedConnections(): void { // ---- Default builder (dynamic import) ---- +const DEV_TRACKER_LONG_POLL_TIMEOUT_MS = 10000; + export function _shouldUseLongPollingForDevTrackerProxy(url: string): boolean { try { const parsed = new URL(url, "http://localhost"); @@ -241,15 +243,39 @@ async function defaultBuildConnection( url: string, delays: number[], ): Promise { - const { HubConnectionBuilder, HttpTransportType, LogLevel } = await import( - "@microsoft/signalr" - ); + const { + DefaultHttpClient, + HttpClient, + HubConnectionBuilder, + HttpTransportType, + LogLevel, + NullLogger, + } = await import("@microsoft/signalr"); const builder = new HubConnectionBuilder(); - const withUrlOptions = _shouldUseLongPollingForDevTrackerProxy(url) - ? { transport: HttpTransportType.LongPolling } + const useDevTrackerLongPolling = _shouldUseLongPollingForDevTrackerProxy(url); + const withUrlOptions = useDevTrackerLongPolling + ? { + transport: HttpTransportType.LongPolling, + httpClient: new (class extends HttpClient { + private readonly inner = new DefaultHttpClient(NullLogger.instance); + + send(request: Parameters["send"]>[0]) { + if (request.method !== "GET") { + return this.inner.send(request); + } + + return this.inner.send({ + ...request, + timeout: DEV_TRACKER_LONG_POLL_TIMEOUT_MS, + }); + } + })(), + } : undefined; - return (withUrlOptions ? builder.withUrl(url, withUrlOptions) : builder.withUrl(url)) + return (withUrlOptions + ? builder.withUrl(url, withUrlOptions) + : builder.withUrl(url)) .withAutomaticReconnect(delays) // Suppress SignalR's internal console logging. The hub is optional // (failures degrade to polling) and we already handle status via