Skip to content

Commit ac261d8

Browse files
BrennanConroydougbu
authored andcommitted
Don't call close if connect does not succeed (#14114)
- small comment - patch config - fix assert
1 parent a3fd923 commit ac261d8

File tree

4 files changed

+68
-1
lines changed

4 files changed

+68
-1
lines changed

eng/PatchConfig.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Directory.Build.props checks this property using the following condition:
1616
<PropertyGroup Condition=" '$(VersionPrefix)' == '3.0.1' ">
1717
<PackagesInPatch>
1818
Microsoft.AspNetCore.DataProtection.EntityFrameworkCore;
19+
@microsoft/signalr;
1920
</PackagesInPatch>
2021
</PropertyGroup>
2122
</Project>

src/SignalR/clients/ts/signalr/src/WebSocketTransport.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ export class WebSocketTransport implements ITransport {
4949
url = url.replace(/^http/, "ws");
5050
let webSocket: WebSocket | undefined;
5151
const cookies = this.httpClient.getCookieString(url);
52+
let opened = false;
5253

5354
if (Platform.isNode && cookies) {
5455
// Only pass cookies when in non-browser environments
@@ -72,6 +73,7 @@ export class WebSocketTransport implements ITransport {
7273
webSocket.onopen = (_event: Event) => {
7374
this.logger.log(LogLevel.Information, `WebSocket connected to ${url}.`);
7475
this.webSocket = webSocket;
76+
opened = true;
7577
resolve();
7678
};
7779

@@ -94,7 +96,23 @@ export class WebSocketTransport implements ITransport {
9496
}
9597
};
9698

97-
webSocket.onclose = (event: CloseEvent) => this.close(event);
99+
webSocket.onclose = (event: CloseEvent) => {
100+
// Don't call close handler if connection was never established
101+
// We'll reject the connect call instead
102+
if (opened) {
103+
this.close(event);
104+
} else {
105+
let error: any = null;
106+
// ErrorEvent is a browser only type we need to check if the type exists before using it
107+
if (typeof ErrorEvent !== "undefined" && event instanceof ErrorEvent) {
108+
error = event.error;
109+
} else {
110+
error = new Error("There was an error with the transport.");
111+
}
112+
113+
reject(error);
114+
}
115+
};
98116
});
99117
}
100118

src/SignalR/clients/ts/signalr/tests/ServerSentEventsTransport.test.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,27 @@ describe("ServerSentEventsTransport", () => {
4545
});
4646
});
4747

48+
it("connect failure does not call onclose handler", async () => {
49+
await VerifyLogger.run(async (logger) => {
50+
const sse = new ServerSentEventsTransport(new TestHttpClient(), undefined, logger, true, TestEventSource);
51+
let closeCalled = false;
52+
sse.onclose = () => closeCalled = true;
53+
54+
const connectPromise = (async () => {
55+
await sse.connect("http://example.com", TransferFormat.Text);
56+
})();
57+
58+
await TestEventSource.eventSource.openSet;
59+
60+
TestEventSource.eventSource.onerror(new TestMessageEvent());
61+
62+
await expect(connectPromise)
63+
.rejects
64+
.toEqual(new Error("Error occurred"));
65+
expect(closeCalled).toBe(false);
66+
});
67+
});
68+
4869
[["http://example.com", "http://example.com?access_token=secretToken"],
4970
["http://example.com?value=null", "http://example.com?value=null&access_token=secretToken"]]
5071
.forEach(([input, expected]) => {

src/SignalR/clients/ts/signalr/tests/WebSocketTransport.test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,33 @@ describe("WebSocketTransport", () => {
6666
});
6767
});
6868

69+
it("connect failure does not call onclose handler", async () => {
70+
await VerifyLogger.run(async (logger) => {
71+
(global as any).ErrorEvent = TestErrorEvent;
72+
const webSocket = new WebSocketTransport(new TestHttpClient(), undefined, logger, true, TestWebSocket);
73+
let closeCalled = false;
74+
webSocket.onclose = () => closeCalled = true;
75+
76+
let connectComplete: boolean = false;
77+
const connectPromise = (async () => {
78+
await webSocket.connect("http://example.com", TransferFormat.Text);
79+
connectComplete = true;
80+
})();
81+
82+
await TestWebSocket.webSocket.closeSet;
83+
84+
expect(connectComplete).toBe(false);
85+
86+
TestWebSocket.webSocket.onclose(new TestEvent());
87+
88+
await expect(connectPromise)
89+
.rejects
90+
.toThrow("There was an error with the transport.");
91+
expect(connectComplete).toBe(false);
92+
expect(closeCalled).toBe(false);
93+
});
94+
});
95+
6996
[["http://example.com", "ws://example.com?access_token=secretToken"],
7097
["http://example.com?value=null", "ws://example.com?value=null&access_token=secretToken"],
7198
["https://example.com?value=null", "wss://example.com?value=null&access_token=secretToken"]]

0 commit comments

Comments
 (0)