4

Im having some problem when joining Electron and Python using web sockets (mostly as a learning experience):

  • Build a desktop app using Electron Ok

  • Build a Python program that monitors some things Ok

  • Connect Python with Electron using socket.io Not working

First I tested socket.io in python with the 'latency' example in https://github.com/miguelgrinberg/python-socketio/tree/master/examples/server/aiohttp. It worked great when I took a look at http://localhost:8080/ in Chrome.

The next step was to ask Electron to load the same url in the desktop app with mainWindow.loadURL('http://localhost:8080') (I used the template from the official electron-quick-start example). I just had to add two lines into the html as shown in here: Electron: jQuery is not defined for jquery to load correctly in Electron, but it again worked nicely.

Now I tried to create an index.html with the same content as latency.html and load it with mainWindow.loadFile('gui/index.html'). I changed the line var socket = io.connect(); for var socket = io.connect('ws://localhost:8080'); (I did also tried ws://127.0.0.1:8080 and ws://192.168.<x>.<x>:8080). The html file loads correctly but the socket begins to connect and disconnect repeatedly with a Bad Request error (I added two console.log lines):

(console.log) connected
(error)       POST http://localhost:8080/socket.io/?EIO=3&transport=polling&t=MosNuF3&sid=c62ce5a6090c4b72bf3f7c6916da6ce7 400 (Bad Request)   **polling-xhr.js:264**
(console.log) disconnected
(warning)     websocket.js:235 WebSocket connection to 'ws://localhost:8080/socket.io/?EIO=3&transport=websocket&sid=c62ce5a6090c4b72bf3f7c6916da6ce7' failed: WebSocket is closed before the connection is established.
(error)       POST http://localhost:8080/socket.io/?EIO=3&transport=polling&t=MosNuFS&sid=c62ce5a6090c4b72bf3f7c6916da6ce7 400 (Bad Request)   **polling-xhr.js:264**
(console.log) connected
etc...
(console.log) disconnected
etc...

On the server side there is also an error when I stop the Electron app:

Unhandled exception
Traceback (most recent call last):
  File "D:\Programming\Tools\Anaconda3\lib\site-packages\aiohttp\web_protocol.py", line 447, in start
    await resp.prepare(request)
  File "D:\Programming\Tools\Anaconda3\lib\site-packages\aiohttp\web_response.py", line 353, in prepare
    return await self._start(request)
  File "D:\Programming\Tools\Anaconda3\lib\site-packages\aiohttp\web_response.py", line 667, in _start
    return await super()._start(request)
  File "D:\Programming\Tools\Anaconda3\lib\site-packages\aiohttp\web_response.py", line 410, in _start
    await writer.write_headers(status_line, headers)
  File "D:\Programming\Tools\Anaconda3\lib\site-packages\aiohttp\http_writer.py", line 112, in write_headers
    self._write(buf)
  File "D:\Programming\Tools\Anaconda3\lib\site-packages\aiohttp\http_writer.py", line 67, in _write
    raise ConnectionResetError('Cannot write to closing transport')
ConnectionResetError: Cannot write to closing transport

What does this Bad Request error mean in this context ? How would the connection work correctly ?

Thanks.

Ediolot
  • 501
  • 2
  • 6
  • 19

1 Answers1

5

In case someone hits the same problem. The answer is pretty simple, from the documentation for socket.io here:

For security reasons, this server enforces a same-origin policy by default. In practical terms, this means the following:

  • If an incoming HTTP or WebSocket request includes the Origin header, this header must match the scheme and host of the connection URL. In case of a mismatch, a 400 status code response is returned and the connection is rejected.
  • No restrictions are imposed on incoming requests that do not include the Origin header.

If necessary, the cors_allowed_origins option can be used to allow other origins. This argument can be set to a string to set a single allowed origin, or to a list to allow multiple origins. A special value of '*' can be used to instruct the server to allow all origins, but this should be done with care, as this could make the server vulnerable to Cross-Site Request Forgery (CSRF) attacks.

When using electron to load the gui, the server is not the same as the python server that's doing the monitoring, thus the Bad Request (not same origin). The solution is to just modify as follows the server properties adding cors_allowed_origins='*':

socketio.AsyncServer(async_mode='aiohttp', cors_allowed_origins='*')
Ediolot
  • 501
  • 2
  • 6
  • 19