Sam Parsons

bypassing CORS restrictions in Electron

September 30, 2019

The engineering team at Swell has had to create and re-create solutions for allowing an Electron application to make cross-origin requests to servers, which is a problem if the requests are made from the Chromium instance that is basically a barebones browser window - with the same restrictions you would encounter in Chrome or Firefox. If requests are made from the Chromium instance and the endpoint doesn’t send ‘Allow-Control-Allow-Origin’ headers, you may recieve an error for the request or incomplete response data - certainly the response headers won’t all be there. This article won’t include a comprehensive description of all CORS-related issues, you can find that here or in many other places via Google search, but it will talk about how the Swell team was able to create an Electron application that is not restricted by this common scenario.

Proxy Server

The initial solution to this problem was to send requests from an environment that was not limited by CORS restrictions - enter the proxy server. By definition, a proxy server is an intermediary between a client and another server - in our case that is the Chromium instance and the user-specified endpoint, respectively. Because a Node server was making the actual request to the endpoint, the responses came back error-free with full headers.

PROXY DIAGRAM

This solved the central problem, but created performance reductions for unary requests (multiple fetch requests being made), had to be coupled to the features required of the Chromium instance (increasing developer time) and wasn’t incredibly intutive for new developers to start working with. As daunting as these problems may seem, this gave the Swell team the opportunity to come up with a better solution.

Electron’s Inter-Process Communication

As the latest iteration of Swell began, the team saw an opportunity to utilize the internal structure of an Electron app to not only bypass CORS restrictions, but eliminate the use of a proxy server. Every Electron app has a “main” Node process that spins at least one “renderer” Chromium process, which becomes the GUI in most cases. Couldn’t we just use the Node process to make these network calls? Yes, but how do we communicate between the two environments? Electron’s Inter-Process Communication (IPC) API to the rescue. IPC can send messages back and forth between the Node and Chromium processes much like clients and servers can communicate over HTTP - sending pieces of data by value (not by reference). The team implemented a few custom listeners on each environment and the optimal solution to the CORS problem was born.

IPC DIAGRAM

With this approach, the team utilized a feature built into an Electron appplication’s architecture, eliminating the need of a proxy server and most importantly eliminating multiple fetch requests, decreasing unary network activity times by up to 60%. While this worked for any network activity that followed simple request-response protocol, the streaming technologies remained in the Chromium instance - if it ain’t broke, don’t fix it. It could be possible to move streaming protocols down to the Node process, but HTTP2 is still experimental in Node environments and attempting recurrent WebSocket connections in Node gave us a gnarly, intractable bug (stacked event handlers) - so we decided to leave it alone for the time being.

Wrap Up

Either of these two solutions will work to solve CORS issues in your Electron app, but leveraging an API available in all Electron apps to reduce the amount of network calls and boost request-response speed seems to be a great solution if your app needs to worry about those metrics. Swell is a particular use case, letting users make a connection to any endpoint - going through all of this optimization may not be needed in most other cases, especially if you have control over the how the backend is implemented. Let us know any feedback or issues you have with using Swell, and it’s always Pull-Request’o’clock for anybody that feels the need.

Thanks, Swell Team


Sam ParsonsSam Parsons

Sam Parsons is currently a Software Engineer at Codesmith. He is also a contributor to Swell, an API development tool for streaming technologies (HTTP2, WS, SSE).