Skip to content

Commit 2264c49

Browse files
author
ionut.stan
committed
Made websockets work in the browser and made the node code compatible with browser exported code.
1 parent ba10b04 commit 2264c49

File tree

10 files changed

+160
-101
lines changed

10 files changed

+160
-101
lines changed

builds/browser/es5/jsonrpc.min.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

builds/browser/es5/jsonrpc.min.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

index_webpack.js

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
11
// Do not use const here, webpack/babel issues.
2-
var objExports = {
2+
module.exports = {
33
JSONRPC: require("./index")
44
};
5-
6-
delete objExports.JSONRPC.Plugins.Client.WebSocketTransport;
7-
delete objExports.JSONRPC.Plugins.Client.ProcessStdIOTransport;
8-
9-
module.exports = objExports;

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "jsonrpc-bidirectional",
33
"description": "Bidirectional JSONRPC over web sockets or HTTP with extensive plugin support.",
4-
"version": "2.1.5",
4+
"version": "2.1.11",
55
"scripts": {
66
"build": "node build.js",
77
"test": "node tests/main.js",

src/BidirectionalWebsocketRouter.js

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ JSONRPC.Utils = require("./Utils");
1212

1313
const EventEmitter = require("events");
1414

15+
const WebSocket = require("ws");
16+
1517

1618
/**
1719
* The "madeReverseCallsClient" event offers automatically instantiated API clients (API clients are instantiated for each connection, lazily).
@@ -57,7 +59,7 @@ class BidirectionalWebsocketRouter extends EventEmitter
5759
*/
5860
async addWebSocket(webSocket)
5961
{
60-
if(webSocket.readyState === webSocket.constructor.CLOSED)
62+
if(webSocket.readyState === WebSocket.CLOSED)
6163
{
6264
// WebSocket.CLOSING should be followed by a closed event.
6365
// WebSocket.OPEN is desired.
@@ -81,33 +83,37 @@ class BidirectionalWebsocketRouter extends EventEmitter
8183

8284
this._objSessions[nWebSocketConnectionID] = objSession;
8385

84-
webSocket.on(
86+
webSocket.addEventListener(
8587
"close",
86-
(code, message) => {
88+
(closeEvent) => {
89+
//closeEvent.code;
90+
//closeEvent.reason;
91+
//closeEvent.wasClean;
92+
8793
delete this._objSessions[nWebSocketConnectionID];
8894
}
8995
);
9096

91-
webSocket.on(
97+
webSocket.addEventListener(
9298
"error",
9399
(error) => {
94100
delete this._objSessions[nWebSocketConnectionID];
95101

96-
if(webSocket.readyState === webSocket.constructor.OPEN)
102+
if(webSocket.readyState === WebSocket.OPEN)
97103
{
98104
webSocket.close(
99-
/* CloseEvent.Internal Error */ 1011,
105+
/*CLOSE_NORMAL*/ 1000, // Chrome only supports 1000 or the 3000-3999 range ///* CloseEvent.Internal Error */ 1011,
100106
error.message
101107
);
102108
}
103109
}
104110
);
105111

106-
webSocket.on(
112+
webSocket.addEventListener(
107113
"message",
108-
async (strMessage) =>
114+
async (messageEvent) =>
109115
{
110-
await this._routeMessage(strMessage, objSession);//.then(() => {}).catch(console.error);
116+
await this._routeMessage(messageEvent.data, objSession);//.then(() => {}).catch(console.error);
111117
}
112118
);
113119

@@ -222,7 +228,7 @@ class BidirectionalWebsocketRouter extends EventEmitter
222228

223229
console.log("[" + process.pid + "] Unclean state. Unable to match WebSocket message to an existing Promise or qualify it as a request or response.");
224230
webSocket.close(
225-
/* CloseEvent.Internal Error */ 1011,
231+
/*CLOSE_NORMAL*/ 1000, // Chrome only supports 1000 or the 3000-3999 range ///* CloseEvent.Internal Error */ 1011,
226232
"Unclean state. Unable to match WebSocket message to an existing Promise or qualify it as a request or response."
227233
);
228234

@@ -235,7 +241,7 @@ class BidirectionalWebsocketRouter extends EventEmitter
235241
{
236242
if(!this._jsonrpcServer)
237243
{
238-
if(webSocket.readyState === webSocket.constructor.OPEN)
244+
if(webSocket.readyState === WebSocket.OPEN)
239245
{
240246
webSocket.send(JSON.stringify({
241247
id: null,
@@ -290,7 +296,7 @@ class BidirectionalWebsocketRouter extends EventEmitter
290296

291297
await this._jsonrpcServer.processRequest(incomingRequest);
292298

293-
if(webSocket.readyState !== webSocket.constructor.OPEN)
299+
if(webSocket.readyState !== WebSocket.OPEN)
294300
{
295301
console.error("webSocket.readyState: " + JSON.stringify(webSocket.readyState) + ". Request was " + strMessage + ". Attempted responding with " + JSON.stringify(incomingRequest.callResultToBeSerialized, undefined, "\t") + ".");
296302
}
@@ -306,7 +312,7 @@ class BidirectionalWebsocketRouter extends EventEmitter
306312
{
307313
if(!this._jsonrpcServer)
308314
{
309-
if(webSocket.readyState === webSocket.constructor.OPEN)
315+
if(webSocket.readyState === WebSocket.OPEN)
310316
{
311317
webSocket.send(JSON.stringify({
312318
id: null,
@@ -319,10 +325,10 @@ class BidirectionalWebsocketRouter extends EventEmitter
319325
}
320326
}
321327

322-
if(webSocket.readyState === webSocket.constructor.OPEN)
328+
if(webSocket.readyState === WebSocket.OPEN)
323329
{
324330
webSocket.close(
325-
/* CloseEvent.Internal Error */ 1011,
331+
/*CLOSE_NORMAL*/ 1000, // Chrome only supports 1000 or the 3000-3999 range ///* CloseEvent.Internal Error */ 1011,
326332
"How can the client be not initialized, and yet getting responses from phantom requests? Closing websocket."
327333
);
328334
}
@@ -355,7 +361,7 @@ class BidirectionalWebsocketRouter extends EventEmitter
355361
&& this._objSessions[nWebSocketConnectionID].clientWebSocketTransportPlugin === null
356362
)
357363
{
358-
if(webSocket.readyState === webSocket.constructor.OPEN)
364+
if(webSocket.readyState === WebSocket.OPEN)
359365
{
360366
webSocket.send(JSON.stringify({
361367
id: null,
@@ -368,11 +374,11 @@ class BidirectionalWebsocketRouter extends EventEmitter
368374
}
369375
}
370376

371-
if(webSocket.readyState === webSocket.constructor.OPEN)
377+
if(webSocket.readyState === WebSocket.OPEN)
372378
{
373379
console.log("[" + process.pid + "] Unclean state. Closing websocket.");
374380
webSocket.close(
375-
/* CloseEvent.Internal Error */ 1011,
381+
/*CLOSE_NORMAL*/ 1000, // Chrome only supports 1000 or the 3000-3999 range ///* CloseEvent.Internal Error */ 1011,
376382
"Unclean state. Closing websocket."
377383
);
378384
}

src/Plugins/Client/WebSocketTransport.js

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ JSONRPC.Utils = require("../../Utils");
44

55
const assert = require("assert");
66

7+
const WebSocket = require("ws");
8+
9+
710
module.exports =
811
class WebSocketTransport extends JSONRPC.ClientPluginBase
912
{
@@ -57,7 +60,7 @@ class WebSocketTransport extends JSONRPC.ClientPluginBase
5760
console.error(error);
5861
console.error("Unable to parse JSON. RAW remote response: " + strResponse);
5962
this._webSocket.close(
60-
/* CloseEvent.Internal Error */ 1011,
63+
/*CLOSE_NORMAL*/ 1000, // Chrome only supports 1000 or the 3000-3999 range ///* CloseEvent.Internal Error */ 1011,
6164
"Unable to parse JSON. RAW remote response: " + strResponse
6265
);
6366

@@ -74,7 +77,7 @@ class WebSocketTransport extends JSONRPC.ClientPluginBase
7477
console.error(new Error("RAW remote message: " + strResponse));
7578
console.log("[" + process.pid + "] Unclean state. Unable to match WebSocket message to an existing Promise or qualify it as a request.");
7679
this.webSocket.close(
77-
/* CloseEvent.Internal Error */ 1011,
80+
/*CLOSE_NORMAL*/ 1000, // Chrome only supports 1000 or the 3000-3999 range ///* CloseEvent.Internal Error */ 1011,
7881
"Unclean state. Unable to match WebSocket message to an existing Promise or qualify it as a request."
7982
);
8083

@@ -105,7 +108,7 @@ class WebSocketTransport extends JSONRPC.ClientPluginBase
105108
return;
106109
}
107110

108-
if(this.webSocket.readyState !== this.webSocket.constructor.OPEN)
111+
if(this.webSocket.readyState !== WebSocket.OPEN)
109112
{
110113
throw new Error("WebSocket not connected.");
111114
}
@@ -161,14 +164,14 @@ class WebSocketTransport extends JSONRPC.ClientPluginBase
161164
{
162165
//assert(webSocket.constructor.name === "WebSocket");
163166

164-
this._webSocket.on(
167+
this._webSocket.addEventListener(
165168
"close",
166-
(code, message) => {
167-
this.rejectAllPromises(new Error("WebSocket closed. Code: " + JSON.stringify(code) + ". Message: " + JSON.stringify(message) + "."));
169+
(closeEvent) => {
170+
this.rejectAllPromises(new Error("WebSocket closed. Code: " + JSON.stringify(closeEvent.code) + ". Message: " + JSON.stringify(closeEvent.reason) + ". wasClean: " + JSON.stringify(closeEvent.wasClean)));
168171
}
169172
);
170173

171-
this._webSocket.on(
174+
this._webSocket.addEventListener(
172175
"error",
173176
(error) => {
174177
this.rejectAllPromises(error);
@@ -177,10 +180,10 @@ class WebSocketTransport extends JSONRPC.ClientPluginBase
177180

178181
if(!this._bBidirectionalWebSocketMode)
179182
{
180-
this._webSocket.on(
183+
this._webSocket.addEventListener(
181184
"message",
182-
async (strMessage) => {
183-
await this.processResponse(strMessage);
185+
async (messageEvent) => {
186+
await this.processResponse(messageEvent.data);
184187
}
185188
);
186189
}

src/Server.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,11 @@ class Server extends EventEmitter
3737
*
3838
* @param {http.Server} httpServer
3939
* @param {string} strRootPath
40+
* @param {boolean} bSharedWithWebSocketServer
4041
*/
41-
async attachToHTTPServer(httpServer, strRootPath)
42+
async attachToHTTPServer(httpServer, strRootPath, bSharedWithWebSocketServer)
4243
{
44+
bSharedWithWebSocketServer = !!bSharedWithWebSocketServer;
4345
assert(typeof strRootPath === "string", typeof strRootPath);
4446

4547
strRootPath = JSONRPC.EndpointBase.normalizePath(strRootPath);
@@ -57,6 +59,21 @@ class Server extends EventEmitter
5759
return;
5860
}
5961

62+
if(httpRequest.headers["sec-websocket-version"])
63+
{
64+
if(bSharedWithWebSocketServer)
65+
{
66+
// Do not call .end() here, or co-existing HTTP handlers on the same server will not have a chance to set headers or respond.
67+
// httpResponse.end();
68+
return;
69+
}
70+
71+
console.error("Received websocket upgrade request, yet not sharing the HTTP connection with a WebSocket.");
72+
httpResponse.statusCode = 403; //Forbidden.
73+
httpResponse.end();
74+
return;
75+
}
76+
6077
try
6178
{
6279
// Default.

0 commit comments

Comments
 (0)