socketio / socket.io

Realtime application framework (Node.JS server)
https://socket.io
MIT License
61.08k stars 10.11k forks source link

[Bug]: WebRequest of socket.io-client can not be intercepted by Electron main process #5113

Open leiming opened 2 years ago

leiming commented 2 years ago

Describe the bug WebRequest of socket.io-client can not be intercepted by Electron main process

To Reproduce

Socket.IO server version: 2.x.x, 3.x.x, 4.x.x

Server

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")
})

Socket.IO client version: 2.x.x, 3.x.x, 4.x.x

Client

// Modules to control application life and create native browser window
const { app, BrowserWindow, session } = require('electron')
const path = require('path')
const io = require('socket.io-client')

function createWindow() {
  // Create the browser window.
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })

  // and load the index.html of the app.
  mainWindow.loadFile('index.html')

  // Open the DevTools.
  // mainWindow.webContents.openDevTools()
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
  createWindow()
  setWebRequest()
  createSocket()

  app.on('activate', function () {
    // On macOS it's common to re-create a window in the app when the
    // dock icon is clicked and there are no other windows open.
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') app.quit()
})

// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.

function setWebRequest () {
   console.log('--setWebRequest--')
  const ses = session.defaultSession

  ses.webRequest.onErrorOccurred((details) => {
    console.log('--onErrorOccurred--', details.url)
    console.log(details.error)
  })

  ses.webRequest.onBeforeRequest((_details, callback) => {
    console.log('--onBeforeRequest--', _details.url)
    callback({ cancel: false })
  })

  ses.webRequest.onBeforeSendHeaders((_details, callback) => {
    console.log('--onBeforeSendHeaders--', _details.url)
    callback({ cancel: false })
  })

  ses.webRequest.onHeadersReceived((_details, callback) => {
    console.log('--onHeadersReceived--', _details.url)
    callback({ cancel: false })
  })

  ses.webRequest.onResponseStarted((_details) => {
    console.log('--onResponseStarted--', _details.url)
  })

  ses.webRequest.onSendHeaders((_details) => {
    console.log('--onSendHeaders--', _details.url)
  })

  ses.webRequest.onCompleted((_details) => {
    console.log('--onCompleted--', _details.url)
  })
}

function createSocket() {
  console.log('--createSocket--')
  const socket = io("http://localhost:3000")

  socket.on('connect', () => {
    console.log('--connect--')
        socket.emit('chat message', 'hello');
  })

  socket.on('connection', (soc) => {
    console.log('--connection--')
  })

  socket.on('error', (error) => {
    console.log('--error--', error)
  })

  socket.on('connect_timeout', (timeout) => {
    console.log('--connect_timeout--', timeout)
  })

  socket.on('connect_error', (error) => {
    console.log('--connect_error--', error)
  })

  socket.on('handshake', (handshake) => {
    console.log('--handshake--', handshake)
  })
}

Expected behavior The socket request shoud be catched by onBeforeRequest, onBeforeSendHeaders:

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

Platform:

Additional context

Electron testcase Gist URL

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

leiming commented 2 years ago

Reference issue by Electron is: https://github.com/electron/electron/issues/35095