In Electron, I'm trying to get files that would normally have a
file://
url origin
to be served instead from
localhost.
In order to do this I've set up an internal http server in the electron app to handle serving pages (full code is quark.js below).
server = spawn("node", [path.join(opts.dir, "../../../app.asar.unpacked/http/page-server.js")], {
env: {
QUARK_PORT: opts.port || 21048,
QUARK_DIR: opts.dir || __dirname,
QUARK_DESC: opts.description || "default",
QUARK_LOG: opts.log || false
}});
Problem - The above works on my machine with Node installed but NodeJS is not available on the production machines.
Question - This you can fork nodejs file inside electron process would suggest you can do this without having NodeJS on the production machines. Is this correct? I can't seem to get this working with error no 'on' method of undefined
when I try to following instead of spawn.
const { fork } = require("child_process");
server = fork(
path.join(opts.dir, "../../../app.asar.unpacked/http/page-server.js"),
[],
{
env: {
QUARK_PORT: opts.port || 21048,
QUARK_DIR: opts.dir || __dirname,
QUARK_DESC: opts.description || "default",
QUARK_LOG: opts.log || false
}
}
);
Raw files and folder structure
Summary
- main.ts - The usual electron main process but calling quark.js to set up http server
- quark.js - Sets up http server
- page-server.js - Serves pages
main.ts (electron)
import { app, BrowserWindow } from "electron";
import * as path from "path";
const os = require("os");
const quark = require("../../http/quark");
quark({
port: 3000,
dir: path.join(__dirname, "../../../app.asar.unpacked/dist/procurement-app"),
description: "HTTP Server"
});
let win: BrowserWindow;
function createWindow() {
win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
});
win.loadURL(quark.url(`index.html`));
win.on("closed", () => {
win = null;
});
}
app.on("ready", createWindow);
app.on("window-all-closed", () => {
if (process.platform !== "darwin") {
app.quit();
}
});
app.on("activate", () => {
if (win === null) {
createWindow();
}
});
quark.js
/**
* To get Auth0 to work by using an internal express server in my electron app to handle serving pages.
* Otherwise the lock fails with a 403 error and responds with "Origin file:// is not allowed".
*
* https://stackoverflow.com/questions/48465130/electron-auth0lock-origin-file-not-allowed/48466642#48466642
* https://github.com/lawrencezahner/quark
*/
const { spawn } = require("child_process");
const path = require("path");
const url = require("url");
let server;
var quark = function(opts) {
if (server == null) {
server = spawn(
"node",
[path.join(opts.dir, "../../../app.asar.unpacked/http/page-server.js")],
{
env: {
QUARK_PORT: opts.port || 21048,
QUARK_DIR: opts.dir || __dirname,
QUARK_DESC: opts.description || "default",
QUARK_LOG: opts.log || false
}
}
).on("error", err => {
console.log("spawn error");
throw err;
});
server.opts = opts;
/** Logging */
server.stdout.on("data", data => {
console.log(data.toString());
});
server.stderr.on("data", data => {
console.log(data.toString());
});
}
};
quark.url = function(path) {
return url.format({
hostname: "localhost",
port: server.opts.port,
pathname: path,
protocol: "http"
});
};
quark.html = function(path) {
return quark.url(`${path}.html`);
};
quark.js = function(path) {
return quark.url(`${path}.js`);
};
quark.scss = function(path) {
return quark.url(`${path}.scss`);
};
module.exports = quark;
page-server.js
const http = require("http");
const path = require("path");
const url = require("url");
const fs = require("fs");
const mime = require("mime-types");
const server = http.createServer(function(req, res) {
/** Logging */
console.log(`${req.method} ${req.url}`);
var purl = url.parse(req.url);
var pathname = path.join(
process.env.QUARK_DIR,
"../../../app.asar.unpacked/dist/procurement-app",
purl.pathname
);
var ext = path.parse(pathname).ext;
fs.exists(pathname, exists => {
if (!exists) {
res.statusCode = 404;
res.end(`Could not find ${pathname} :(`);
return;
} else {
fs.readFile(pathname, (err, data) => {
if (err) {
res.statusCode = 500;
res.end(`Had trouble getting ${pathname}`);
} else {
res.setHeader("Content-type", mime.contentType(ext) || "text/plain");
res.setHeader(
"Access-Control-Allow-Origin",
url.format({
hostname: "localhost",
port: process.env.QUARK_PORT,
protocol: "http"
})
);
res.end(data);
return;
}
});
}
});
});
server.listen(process.env.QUARK_PORT);
/** Logging */
console.log(`Quark Server started on ${process.env.QUARK_PORT}`);
folder structure
├───app-builds
│ ├───.icon-ico
│ └───win-unpacked
│ ├───locales
│ ├───resources
│ │ └───app.asar.unpacked
│ │ ├───dist
│ │ │ └───procurement-app
│ │ ├───http
│ │ └───node_modules
│ │ ├───mime-db
│ │ └───mime-types
│ └───swiftshader
├───dist
│ └───procurement-app
│ └───assets
│ ├───icons
│ └───images
├───electron
│ └───[main.ts]
│ └───dist
│ └───[main.js]
├───http
│ └───[page-server.js, quark.js]
├───node_modules
└───src
└───app
Note I'm following the answer to this question Electron Auth0Lock "Origin file:// not allowed" (the question is the same reason I'm trying to do this)