This repository was archived by the owner on Jan 5, 2026. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 292
Expand file tree
/
Copy pathnodeWebSocketClient.ts
More file actions
116 lines (104 loc) · 4.39 KB
/
nodeWebSocketClient.ts
File metadata and controls
116 lines (104 loc) · 4.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/**
* @module botframework-streaming
*/
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
import { ProtocolAdapter } from '../protocolAdapter';
import { RequestHandler } from '../requestHandler';
import { StreamingRequest } from '../streamingRequest';
import { RequestManager } from '../payloads';
import { PayloadReceiver, PayloadSender, TransportDisconnectedEvent } from '../payloadTransport';
import { NodeWebSocket } from './nodeWebSocket';
import { WebSocketTransport } from './webSocketTransport';
import { IStreamingTransportClient, IReceiveResponse } from '../interfaces';
/**
* Web socket based client to be used as streaming transport.
*/
export class WebSocketClient implements IStreamingTransportClient {
private readonly _url: string;
private readonly _requestHandler: RequestHandler;
private readonly _sender: PayloadSender;
private readonly _receiver: PayloadReceiver;
private readonly _requestManager: RequestManager;
private readonly _protocolAdapter: ProtocolAdapter;
private readonly _disconnectionHandler: (message: string) => void;
/**
* Creates a new instance of the [WebSocketClient](xref:botframework-streaming.WebSocketClient) class.
*
* @param config For configuring a [WebSocketClient](xref:botframework-streaming.WebSocketClient) instance to communicate with a WebSocket server.
* @param config.url The URL of the remote server to connect to.
* @param config.requestHandler The [RequestHandler](xref:botframework-streaming.RequestHandler) used to process incoming messages received by this client.
* @param config.disconnectionHandler Optional function to handle the disconnection message.
*/
constructor({
url,
requestHandler,
disconnectionHandler = null,
}: {
url: string;
requestHandler: RequestHandler;
disconnectionHandler: (message: string) => void;
}) {
this._url = url;
this._requestHandler = requestHandler;
this._disconnectionHandler = disconnectionHandler;
this._requestManager = new RequestManager();
this._sender = new PayloadSender();
this._sender.disconnected = this.onConnectionDisconnected.bind(this);
this._receiver = new PayloadReceiver();
this._receiver.disconnected = this.onConnectionDisconnected.bind(this);
this._protocolAdapter = new ProtocolAdapter(
this._requestHandler,
this._requestManager,
this._sender,
this._receiver,
);
}
/**
* Establish a connection with no custom headers.
*
* @returns A promise that will not resolve until the client stops listening for incoming messages.
*/
async connect(): Promise<void> {
const ws = new NodeWebSocket();
try {
await ws.connect(this._url);
const transport = new WebSocketTransport(ws);
this._sender.connect(transport);
this._receiver.connect(transport);
} catch (_error) {
throw new Error('Unable to connect client to Node transport.');
}
}
/**
* Stop this client from listening.
*/
disconnect(): void {
this._sender.disconnect(new TransportDisconnectedEvent('Disconnect was called.'));
this._receiver.disconnect(new TransportDisconnectedEvent('Disconnect was called.'));
}
/**
* Task used to send data over this client connection.
*
* @param request The [StreamingRequest](xref:botframework-streaming.StreamingRequest) instance to send.
* @returns A promise that will produce an instance of receive response on completion of the send operation.
*/
async send(request: StreamingRequest): Promise<IReceiveResponse> {
return this._protocolAdapter.sendRequest(request);
}
private onConnectionDisconnected(sender: Record<string, unknown>, args: any): void {
// Rejects all pending requests on disconnect.
this._requestManager.rejectAllResponses(new Error('Disconnect was called.'));
if (this._disconnectionHandler != null) {
this._disconnectionHandler('Disconnected');
return;
}
throw new Error(
`Unable to re-connect client to Node transport for url ${this._url}. Sender: '${JSON.stringify(
sender,
)}'. Args:' ${JSON.stringify(args)}`,
);
}
}