Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request]: Allow session.webRequest in main process to catch WebSocket using socket.io-client #35095

Closed
3 tasks done
leiming opened this issue Jul 27, 2022 · 10 comments
Closed
3 tasks done

Comments

@leiming
Copy link

leiming commented Jul 27, 2022

Preflight Checklist

Electron Version

19.x.x, 18.x.x, 17.x.x, 16.x.x

What operating system are you using?

Windows

Operating System Version

Windows 10 Version 21H2

What arch are you using?

x64

Last Known Working Electron version

16.x.x

Expected Behavior

The socket request shoud be interrepted by onBeforeRequestonBeforeSendHeaders:

Electron exited with signal SIGTERM.
Saving files to temp directory...
Saved files to C:\Users\BINGZH~1\AppData\Local\Temp\tmp-1716-5xGvP0C8ngIj
Installing node modules using npm: socket.io-client@2.5.0...
  + socket.io-client@2.5.0
added 24 packages from 19 contributors and audited 24 packages in 5.516s
found 0 vulnerabilities
Electron v19.0.6 started.

 --setWebRequest--
 --createSocket--
+ ----onBeforeRequest----
+ ws://localhost:3000/socket.io/?EIO=3&transport=websocket
+ ----onBeforeSendHeaders----
+ ws://localhost:3000/socket.io/?EIO=3&transport=websocket
 --connect--

Actual Behavior

Electron exited with signal SIGTERM.
Saving files to temp directory...
Saved files to C:\Users\BINGZH~1\AppData\Local\Temp\tmp-1716-5xGvP0C8ngIj
Installing node modules using npm: socket.io-client@2.5.0...
  + socket.io-client@2.5.0
added 24 packages from 19 contributors and audited 24 packages in 5.516s
found 0 vulnerabilities
Electron v19.0.6 started.

  --setWebRequest--
  --createSocket--
- ----onBeforeRequest----
- ws://localhost:3000/socket.io/?EIO=3&transport=websocket
- ----onBeforeSendHeaders----
- ws://localhost:3000/socket.io/?EIO=3&transport=websocket
  --onBeforeRequest-- file:///C:/Users/BINGZH~1/AppData/Local/Temp/tmp-1716-5xGvP0C8ngIj/index.html
  --onBeforeSendHeaders-- file:///C:/Users/BINGZH~1/AppData/Local/Temp/tmp-1716-5xGvP0C8ngIj/index.html
  --onSendHeaders-- file:///C:/Users/BINGZH~1/AppData/Local/Temp/tmp-1716-5xGvP0C8ngIj/index.html
  --connect--

Testcase Gist URL

https://gist.github.com/39b56c0169790f1561df3bad80d6c2bf

Additional Information

The Sample of Electron Fiddle dependency by socket.io-client@2.

The ServerSide code is:

node server.js

server.js

const express = require("express")
const app = express()
const http = require("http")
const server = http.createServer(app)
const Server = require("socket.io")
const io = new Server(server)

app.get("/", (req, res) => {
  res.sendFile(__dirname + "/index.html")
})

io.on("connection", (socket) => {
  console.log("a user connected")
  socket.on("disconnect", () => {
    console.log("user disconnected")
  })
})

io.on("connection", (socket) => {
  socket.on("chat message", (msg) => {
    console.log("message: " + msg)
  })
})

server.listen(3000, () => {
  console.log("listening on *:3000")
})

package.json

{
  "dependencies": {
    "express": "4",
    "http": "0.0.1-security",
    "socket.io": "2",
    "socket.io-client": "2"
  }
}
@leiming leiming changed the title [Bug]: session.webRequest can not catch WebSocket using socket.io-client [Bug]: session.webRequest in main process can not catch WebSocket using socket.io-client Jul 27, 2022
@leiming
Copy link
Author

leiming commented Jul 27, 2022

Reference issue by socket.io is:

socketio/socket.io-client#1548

@clavin
Copy link
Member

clavin commented Jul 29, 2022

Hi! I'm trying to confirm that this behavior you're seeing is a bug, but I don't understand. Electron's WebRequest object is just a hook for Chromium's network stack, whereas socket.io likely uses Node's net or tls modules. The two are completely separate and requests in one won't fire events for the other. The behavior you're seeing looks to be expected from that.

I'm going to close this issue for now as it seems to stem from that confusion I described above. Thanks for asking for clarification! 🙂

@clavin clavin closed this as not planned Won't fix, can't repro, duplicate, stale Jul 29, 2022
@leiming
Copy link
Author

leiming commented Jul 29, 2022

@clavin Thanks for replay.

  1. I don't use the socket.io module, just the socket.io-client module, which doesn't and can't depend on net or tls dependencies,because socket.io-client runs mainly inside the browser. Take a closer look at the following example, please:
  1. The socket module is also used as a hot update within webpack in the main process, and its logs can be intercepted via WebRequest.
ws://localhost:1212/sockjs-node/162/phxq3wbq/websocket
----onResponseStarted----
ws://localhost:1212/sockjs-node/162/phxq3wbq/websocket
----onCompleted----
ws://localhost:1212/sockjs-node/162/phxq3wbq/websocket
----onBeforeRequest----
ws://localhost:1212/sockjs-node/492/xue1rpxo/websocket
----onBeforeSendHeaders----
ws://localhost:1212/sockjs-node/492/xue1rpxo/websocket
----onSendHeaders----
ws://localhost:1212/sockjs-node/492/xue1rpxo/websocket
----onHeadersReceived----
ws://localhost:1212/sockjs-node/492/xue1rpxo/websocket
----onResponseStarted----
ws://localhost:1212/sockjs-node/492/xue1rpxo/websocket
----onCompleted----
ws://localhost:1212/sockjs-node/492/xue1rpxo/websocket

Please take a look at this issue again, I am willing to provide all the replications and add any information. Again, thank you very much. @clavin

@leiming
Copy link
Author

leiming commented Jul 31, 2022

The following example simply moves the code from the main process to the rendering process(proload.js) without modifying any of the dependencies or code logic.

socket client on the Node Process, which CANNOT be intercepted via WebRequest:

https://gist.github.com/a75a9f77e9b96154e777197921e4de6e

The Console output receives the incoming logs and intercepts requests as normal.

[4464:0731/154514.370:INFO:CONSOLE(25)] "--connect--", source: C:\Users\BINGZH~1\AppData\Local\Temp\tmp-8068-dfZlwZkjt05D\preload.js (25)
--onBeforeRequest-- ws://localhost:3000/socket.io/?EIO=3&transport=websocket&sid=qKi_CZdlL4mk049XAAAE
--onBeforeSendHeaders-- ws://localhost:3000/socket.io/?EIO=3&transport=websocket&sid=qKi_CZdlL4mk049XAAAE
--onSendHeaders-- ws://localhost:3000/socket.io/?EIO=3&transport=websocket&sid=qKi_CZdlL4mk049XAAAE
--onHeadersReceived-- ws://localhost:3000/socket.io/?EIO=3&transport=websocket&sid=qKi_CZdlL4mk049XAAAE
--onResponseStarted-- ws://localhost:3000/socket.io/?EIO=3&transport=websocket&sid=qKi_CZdlL4mk049XAAAE
--onCompleted-- ws://localhost:3000/socket.io/?EIO=3&transport=websocket&sid=qKi_CZdlL4mk049XAAAE

Comparing with the privous example, maybe this issue not a bug (I'm not sure), but It can not receved the log due to whereas socket.io likely uses Node's net or tls modules. which shoud not be a reason to close this issue.

socket client on the Render Process, which can be intercepted via WebRequest as expected:

https://gist.github.com/39b56c0169790f1561df3bad80d6c2bf

The both example work with the sample server example:

server.js

const express = require("express")
const app = express()
const http = require("http")
const server = http.createServer(app)
const Server = require("socket.io")
const io = new Server(server)

app.get("/", (req, res) => {
  res.sendFile(__dirname + "/index.html")
})

io.on("connection", (socket) => {
  console.log("a user connected")
  socket.on("disconnect", () => {
    console.log("user disconnected")
  })
})

io.on("connection", (socket) => {
  socket.on("chat message", (msg) => {
    console.log("message: " + msg)
  })
})

server.listen(3000, () => {
  console.log("listening on *:3000")
})

package.json

{
  "dependencies": {
    "express": "4",
    "http": "0.0.1-security",
    "socket.io": "2",
    "socket.io-client": "2"
  }
}

@codebytere @RaisinTen @clavin

Please consider is issue again and consider reopen this issue, thank you very much.

@RaisinTen
Copy link
Contributor

Reopening since the OP stated that they're using socket.io-client and not socket.io which uses net / tls from node.

@RaisinTen RaisinTen reopened this Aug 1, 2022
@clavin
Copy link
Member

clavin commented Aug 1, 2022

I'm sorry, I still don't understand. 😕 Let me show you the investigation I did before that showed me how socket.io-client does indeed use Node's net or tls modules:

So, to sum that all up, yes, socket.io-client does use net or tls when running in a Node.js environment like the main process in Electron. If socket.io-client runs in Node.js but theoretically doesn't use any of Node's APIs, then how would it be making these websocket connections? Node.js has no built-in websocket implementation.

Like I said earlier, net and tls are Node modules running on a separate network stack from the WebRequest APIs, hence why requests in one don't fire events for the other. That is why when you move your code to a preload script, which moves it into a browser environment with a built-in WebSocket implementation which uses the network stack associated with WebRequest, those events start firing.

This is all to say that this behavior is expected and not a bug in Electron.

Sorry about this confusion! 🙇 When I said socket.io in my last message I meant socket.io-client but did not consider that socket.io was its own separate package. I did indeed investigate socket.io-client when I wrote it, however, so I stick with the rest of what I wrote with that perspective in mind. I'm going to leave it unedited since that mistake became part of the conversation here.

I'll give the OP a couple of days to respond, however my disposition is to still close this issue as not a bug after that time passes.

@leiming
Copy link
Author

leiming commented Aug 3, 2022

@clavin @RaisinTen Thank you very much for such a detailed reply, which directly points out the differences in the implementation of socket.io-client between the Browser and Node.js.

WebSocket is implemented in two different ways depending on environment, either the ws module in Node or using the global WebSocket class in the browser.

My real concern is : in Electron eco, we use session.defaultSession.webRequest to intercepte / handle web requests, however, I am at a loss as to how to handle tls request or net requests in a similar way using Electron API.

From now on, I have understood why by reading the source code of socket.io, but I couldn't find a solution by reading the source code or API documentation of Electron.

So, it's really not a bug, but not sure if it makes enhancement possible? Or maybe I don't understand Electron well enough or read the documentation carefully enough. Anyway, @clavin thanks again for such a patient answer.

@RaisinTen RaisinTen changed the title [Bug]: session.webRequest in main process can not catch WebSocket using socket.io-client [Feature Request]: Allow session.webRequest in main process to catch WebSocket using socket.io-client Aug 4, 2022
@clavin
Copy link
Member

clavin commented Aug 4, 2022

No worries!

Unfortunately, even as a request for an enhancement I still will be closing this issue. The net and tls modules are Node.js modules. If there's missing support for intercepting requests in those modules, that's really more of an enhancement to Node.js than to the Electron project. There's not a simple mapping between Node's network stack and Chromium's to make them play nicely with each other, and even if we did figure out it, the maintenance cost of that implementation might be too high for Electron right now.

So while we appreciate this enhancement request, it's not something that we will be able to implement in the near future. Since we use our issues tab as the team's backlog, we prefer to only retain issues that are on our immediate roadmap. So, I'm closing this feature request as not planned right now. I hope that makes sense!

@clavin clavin closed this as not planned Won't fix, can't repro, duplicate, stale Aug 4, 2022
@rehanvdm
Copy link

rehanvdm commented Sep 9, 2022

I just stumbled over this as well now. With the environment variable set DEBUG=socket.* I get the following when trying to open the client connection within the main electron process.

2022-09-09T04:27:00.395Z socket.io-client:url parse ws://localhost:3000
2022-09-09T04:27:00.396Z socket.io-client new io instance for ws://localhost:3000
2022-09-09T04:27:00.396Z socket.io-client:manager readyState closed
2022-09-09T04:27:00.396Z socket.io-client:manager opening ws://localhost:3000
2022-09-09T04:27:00.412Z socket.io-client:manager connect attempt will timeout after 1000
2022-09-09T04:27:00.414Z socket.io-client:manager readyState opening

Is this the same as what is being described here? The on connect error or on disconnect events never fire, nor does anything else throw an error or "respond"/just looks like it is waiting/hangs.

@leiming @clavin So the conclusion is that we can't run socket.io-client in the electron main process, but it should work in the render process?

@leiming
Copy link
Author

leiming commented Sep 18, 2022

@rehanvdm socket.io-client work fine in Renderer Process:

https://gist.github.com/leiming/a75a9f77e9b96154e777197921e4de6e

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants