electron / electron

:electron: Build cross-platform desktop apps with JavaScript, HTML, and CSS

Home Page:https://electronjs.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[Bug]: Websocket connection in renderer doesn't go through proxy even when session.setProxy used

Bojack92160 opened this issue · comments

Preflight Checklist

Electron Version

18.3.0

What operating system are you using?

Windows

Operating System Version

Windows 10

What arch are you using?

x64

Last Known Working Electron version

don't know

Expected Behavior

I would like to make my websocket connection (as a client) go through a proxy.
For that, I create my websocket in a browser window, and use setProxy on the window.

When I use setProxy on the session of a browser window, I expect it to proxify all connections.

Actual Behavior

The websocket is well opened but does not go through the proxy.
In fact, the 'login' event is not even called.
I have tried to use webContents.session.forceReloadProxyConfig() wihtout success.
If I use loadUrl to go for example on 'https://whatismyipaddress.com/', this request go though the proxy, and the login event is called

Testcase Gist URL

No response

Additional Information

Environment versions:
node 16.15.1
ws 8.6.0

Code:
Here is my code to reproduce:

In the main process:

const { BrowserWindow, ipcMain } = require('electron');

this.win = new BrowserWindow({
    width: 1000,
    height: 600,
    webPreferences: {
        devTools: true,
        nodeIntegration: true,
        contextIsolation: false
    }
});

this.win.webContents.on('login', (event, webContents, request, callback) => {
    console.log(' WM  login with user and password');
    callback('username', 'password');
    this.win.webContents.openDevTools();
});
this.win.webContents.session.setProxy({ proxyRules: 'http://myProxyIp:myProxyPort' });
this.win.loadUrl('./index.html');
this.win.webContents.send('openWs', ['wsUrl']); //method to open ws in render windows

ipcMain.on('error', (event, arg) => {
    console.log(arg);
});

ipcMain.on('close', (event, arg) => {
    console.log(arg);
});
ipcMain.on('message', (event, arg) => {
    console.log(arg)
});
ipcMain.on('message', (event, arg) => {
                console.log(arg)
});


The render process:

index.html:


<!DOCTYPE html>
  <html>
    <head>
      <meta charset="UTF-8">
      <title>Hello World!</title>
    </head>
    <body>
      <h1>Hello World!</h1>
      We are using node <script>document.write(process.versions.node)</script>,
      Chrome <script>document.write(process.versions.chrome)</script>,
      and Electron <script>document.write(process.versions.electron)</script>.
    </body>
    <script>
        require('./renderWs.js');
    </script>
  </html>

renderWs.js :

const Websocket = require('ws');
const ipc = require('electron').ipcRenderer;


ipc.on('openWs', (event, args) => {
	console.log(event, args);
	openWS(...args);
});

async function openWS(url) {



	const ws = new Websocket(url);

	ws.on('open', () => {
		ipc.send('open', 'open');
		console.log('open');

		ipc.on('send', (event, msg) => {
			console.log(event, msg);
			ws.send(msg);
		});
	});

	ws.on('error', (e) => {
		ipc.send('error', e);
		console.log('error', e);
	});

	ws.on('close', (code) => {
		ipc.send('close', close);
		console.log('close', code);
	});

	ws.on('message', (data, isBinary) => {
	
	ipc.send('message', [data, isBinary]);
		console.log('message', !isBinary ? data.toString() : data);
	});

}

You are using the ws package and not the native WebSocket. So this is not a browser API but a Node.js thing (different HTTP stack from the renderer/browser). It can be proxied according to their docs https://www.npmjs.com/package/ws#how-to-connect-via-a-proxy but you shouldn't need that package at all.

thanks for the answer, this explain this behaviour