diff --git a/lib/webSocketServer.js b/lib/webSocketServer.js index a160b79b08..6a6142a114 100644 --- a/lib/webSocketServer.js +++ b/lib/webSocketServer.js @@ -1,4 +1,5 @@ -var WebSocketServer = require("websocket").server; +var websocket = require("websocket"); +var WebSocketServer = websocket.server; module.exports = function(httpServer, provider, logger) { var connectionManager = new ConnectionManager(provider, logger); @@ -43,10 +44,18 @@ ConnectionManager.prototype.manageConnection = function(connection) { }; connection.on("message", function(message) { + let payload; try { - var payload = JSON.parse(message.utf8Data); + if (message.type === "utf8") { + payload = JSON.parse(message.utf8Data); + } else if (message.type === "binary") { + payload = JSON.parse(message.binaryData.toString("utf8").trim()); + } else { + throw new Error("Invalid message type"); + } } catch (e) { - connection.reject(400, "Bad Request"); + connection.close(websocket.connection.CLOSE_REASON_UNPROCESSABLE_INPUT, e.message); + return; } self._logPayload(payload); diff --git a/test/requests.js b/test/requests.js index 4e637f3163..b29af9b262 100644 --- a/test/requests.js +++ b/test/requests.js @@ -1620,6 +1620,53 @@ describe("WebSockets Server:", function() { tests(web3); + it("Can also handle binary websocket data", async() => { + // Python web3 only sends binary over websockets and we should + // be able to handle it. + + // web3.eth.getAccounts transmits over utf8, so use that as our baseline. + const accounts = await web3.eth.getAccounts(); + + // Listen for messages: + const pendingMessage = new Promise((resolve, reject) => { + function message(result) { + cleanup(); + resolve(JSON.parse(result.data)); + } + function close(err) { + cleanup(); + reject(err.reason); + } + function cleanup() { + web3.currentProvider.connection.removeEventListener("message", message); + web3.currentProvider.connection.removeEventListener("close", close); + } + web3.currentProvider.connection.addEventListener("message", message); + web3.currentProvider.connection.addEventListener("close", close); + }); + + // generate a binary jsonrpc message: + const jsonRpc = Buffer.from( + JSON.stringify({ + jsonrpc: "2.0", + id: 9999, + method: "eth_accounts", + params: [] + }) + ); + + // send the binary data: + web3.currentProvider.connection.send(jsonRpc); + const result = await pendingMessage; + + // And compare + assert.deepStrictEqual( + result.result, + accounts.map((a) => a.toLocaleLowerCase()), + "Accounts don't match between binary and utf8 websocket requests!" + ); + }).timeout(500); // fail quick if our hacked-together websocket handler fails. + after("Shutdown server", async function() { let provider = web3._provider; web3.setProvider();