Changing User-Agent Header in an Atom Editor Plugin

When improving Code::Stats’s Atom plugin, I wanted to add the plugin version as the User-Agent header: code-stats-atom/x.y.z. I used the fetch API and set the header there but it did nothing! By googling a bit I found that User-Agent used to be a “dangerous” header that wasn’t allowed to be set in browsers. It was only recently allowed, but Chromium has not implemented support for it.

Because Atom runs on Electron, which is running on Chromium, fetch and XMLHttpRequest were refusing to set the header. The solution I came up with is not nice but it works: I used the Node.js HTTP API. Here’s an excerpt of code-stats-atom’s code:

const http = require('http');
const https = require('https');

...

const url = new URL(UPDATE_URL);

// Node.js has separate APIs for HTTPS and HTTP, need to choose the correct one
const executor = url.protocol === 'https:'? https : http;

const req = executor.request({
  method: 'POST',
  host: url.hostname,
  port: url.port,
  path: url.pathname,
  protocol: url.protocol,
  headers: {
    'X-API-Token': API_KEY,
    'Content-Type': 'application/json',
    'User-Agent': `code-stats-atom/${PACKAGE_VERSION}`
  }
});

req.on('response', response => {
  ...
});

req.on('timeout', () => ...);

req.write(JSON.stringify(data));
req.end();

As I said, it’s ugly but it works. It took me a while to find so I hope this can help others. I tested it in Atom but I don’t see why it wouldn’t work with other Electron apps as well.