Skip to content

Commit 4dfd93c

Browse files
[TS] Wait for handshake response (#2983)
1 parent f0a34a4 commit 4dfd93c

File tree

5 files changed

+105
-69
lines changed

5 files changed

+105
-69
lines changed

clients/ts/signalr/src/HandshakeProtocol.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,11 @@ export class HandshakeProtocol {
5555

5656
// At this point we should have just the single handshake message
5757
const messages = TextMessageFormat.parse(messageData);
58-
responseMessage = JSON.parse(messages[0]);
58+
const response = JSON.parse(messages[0]);
59+
if (response.type) {
60+
throw new Error("Expected a handshake response from the server.");
61+
}
62+
responseMessage = response;
5963

6064
// multiple messages could have arrived with handshake
6165
// return additional data to be parsed as usual, or null if all parsed

clients/ts/signalr/src/HubConnection.ts

+13
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ export class HubConnection {
3131
private id: number;
3232
private closedCallbacks: Array<(error?: Error) => void>;
3333
private receivedHandshakeResponse: boolean;
34+
private handshakeResolver!: (value?: PromiseLike<{}>) => void;
35+
private handshakeRejecter!: (reason?: any) => void;
3436
private connectionState: HubConnectionState;
3537

3638
// The type of these a) doesn't matter and b) varies when building in browser and node contexts
@@ -106,6 +108,11 @@ export class HubConnection {
106108
this.logger.log(LogLevel.Debug, "Starting HubConnection.");
107109

108110
this.receivedHandshakeResponse = false;
111+
// Set up the promise before any connection is started otherwise it could race with received messages
112+
const handshakePromise = new Promise((resolve, reject) => {
113+
this.handshakeResolver = resolve;
114+
this.handshakeRejecter = reject;
115+
});
109116

110117
await this.connection.start(this.protocol.transferFormat);
111118

@@ -120,6 +127,8 @@ export class HubConnection {
120127
this.resetTimeoutPeriod();
121128
this.resetKeepAliveInterval();
122129

130+
// Wait for the handshake to complete before marking connection as connected
131+
await handshakePromise;
123132
this.connectionState = HubConnectionState.Connected;
124133
}
125134

@@ -388,19 +397,23 @@ export class HubConnection {
388397
// We don't want to wait on the stop itself.
389398
// tslint:disable-next-line:no-floating-promises
390399
this.connection.stop(error);
400+
this.handshakeRejecter(error);
391401
throw error;
392402
}
393403
if (responseMessage.error) {
394404
const message = "Server returned handshake error: " + responseMessage.error;
395405
this.logger.log(LogLevel.Error, message);
396406

407+
this.handshakeRejecter(message);
397408
// We don't want to wait on the stop itself.
398409
// tslint:disable-next-line:no-floating-promises
399410
this.connection.stop(new Error(message));
411+
throw new Error(message);
400412
} else {
401413
this.logger.log(LogLevel.Debug, "Server handshake complete.");
402414
}
403415

416+
this.handshakeResolver();
404417
return remainingData;
405418
}
406419

0 commit comments

Comments
 (0)