Get active Websockets of a Website possible?
Asked Answered
R

3

12

I would like to know if its possible to get active WebSockets of a Website. An example would be: var x = document.findWebSocket(). The websockets would be listed in Chrome under the Network Tab (In the dev tools section). From there the websockets are listed under "WS". I want to be able to do x.emit(..); as well.

So far i could only come up with var x = new WebSocket("wss://exampleUrl.com/socket.io/?EIO=3&transport=websocket", "protocol1");. But this only adds a new Websocket with a different sid from the one that i want to emit messages from.

adding "&sid = {SID of Active Websocket}" would not work.

Rive answered 26/1, 2020 at 6:8 Comment(0)
M
24

It's a bit hacky, but if you can inject code that runs before the site's code does (for example, with Tampermonkey and @run-at document-start), you can monkeypatch window.WebSocket so that whenever it's called, you add the created websocket to an array which you can examine later. For example, running the following on Stack Overflow:

// ==UserScript==
// @name             0 New Userscript
// @include          /^https://stackoverflow.com
// @run-at           document-start
// @grant            none
// ==/UserScript==

const sockets = [];
const nativeWebSocket = window.WebSocket;
window.WebSocket = function(...args){
  const socket = new nativeWebSocket(...args);
  sockets.push(socket);
  return socket;
};
setTimeout(() => {
  // or create a button which, when clicked, does something with the sockets
  console.log(sockets);
}, 1000);

results in [WebSocket] being logged (and you could proceed to do whatever you wanted to do with the instance, such as call emit).

Murrell answered 26/1, 2020 at 6:23 Comment(9)
This works, although i think i can give more context. This is regarding the site skribbl.io. It shares its canvas using websockets, and in python people dont have to get this "hacky". So maybe it works in js in a simpler way?Rive
I'm pretty doubtful that there's any other easy option, unfortunately - if you're trying to do client-side tweaking, monkeypatching globals before the site's official script runs is sometimes the best way to do it, even if it seems hacky. You could also enable Chrome Local Overrides and then write your own code into the site's source code stackapps.com/questions/8531 but that's a lot more complicated for the same results - other than saving a reference to the created object, there doesn't look to be a way to get a list of current instancesMurrell
Is it possible for me to create my own websocket in chrome? i do get a session id as first message, but when i send "2probe" it returns 3 instead of 3probeRive
If you create a socket instance, then add an open listener to it, and then .send something, you should be able to communicate with the server. For example: stackoverflow.com/a/59098029 Beyond that, hard to say where the logic is failing without seeing the codeMurrell
Yeah, the problem is i am connecting with a new session id. When i click "play" it creates the websocket with new session_id, which means i join a different lobby at the same time.Rive
"Click play", what do you mean? There isn't anything about a play button (or a lobby) anywhere in the question (or the answer)Murrell
There's no need to monkeypatch before any socket initialization. You can do it at any later point in time and get access to any socket that is sending something for example by monkeypatching WebSocket.prototype.send and saving the this (i.e. that socket instance) from there.Careful
(of course that only works if the client ever sends something)Careful
This is the correct idea and works most of the times. However, it will fail if the original code tries to access the property of WebSocket (e.g., window.WebSocket.OPEN would be undefined). To fix this, Proxy should be used to fix these edge cases. See developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Pentahedron
C
10

You could collect all sockets in an array as soon as they send something:

const originalSend = WebSocket.prototype.send;
window.sockets = [];
WebSocket.prototype.send = function(...args) {
  if (window.sockets.indexOf(this) === -1)
    window.sockets.push(this);
  return originalSend.call(this, ...args);
};

Then later:

if (sockets.length > 0)
  sockets[0].send('hello');
Careful answered 2/8, 2021 at 15:31 Comment(2)
This will work if client code calls someSocket.send(..), but such a situation may well not occur. The server may send a message that the client processes, but the client does not send a message in reply - this situation is extremely common (probably the most common usage of sockets - for on-demand server to client communication).Murrell
I see. I didn't think a client socket that doesn't regularly send stuff was so common. But yeah, now thinking about it, probably it is.Careful
M
0

Here is a method to do this by creating a wrapper in a Chrome extension.

content.js:

const nativeWebSocket = window.WebSocket;

function messageReceived(message) {
    console.log(message)
}

class WebSocket extends nativeWebSocket {
    nativeSend = nativeWebSocket.prototype.send
    saved = false

    send(msg) {
        this.nativeSend(msg)
        this.saved = false
        if (!this.saved) {
            this.saved = true
            this.addEventListener("message", messageReceived)
        }
    }

}

manifest.json:

{
  "manifest_version": 3,
  "name": "Bet It Bot 2",
  "version": "1.0.3",
  "description": "Bet it scrapper",
  "background": {
  },
  "permissions": [
    "webRequest"
  ],
  "content_scripts": [
    {
      "run_at": "document_start",
      "world": "MAIN",
      "js": [
        "scripts/content.js"
      ],
      "matches": [
        "https://www.bet365.it/"
      ]
    }
  ]
}

Important:

  • "run_at": "document_start" is used to start the extenstion before the page is loaded.
  • "world": "MAIN" is used to run both the extension and page on same context.
Metagnathous answered 16/6 at 21:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.