Added clientonly script

Added clientonly script to have server and client run at different locations
This commit is contained in:
Unknown 2017-06-25 12:18:59 +02:00 committed by unknown
parent 8893df118e
commit 66f93ee541
8 changed files with 118 additions and 6 deletions

View File

@ -33,6 +33,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Add ability to change the path of the `custom.css`. - Add ability to change the path of the `custom.css`.
- Add translation Dutch to Alert module. - Add translation Dutch to Alert module.
- Added Romanian translation. - Added Romanian translation.
- Add `clientonly` script to start only the electron client for a remote server
### Updated ### Updated
- Added missing keys to Polish translation. - Added missing keys to Polish translation.

View File

@ -48,6 +48,11 @@ bash -c "$(curl -sL https://raw.githubusercontent.com/MichMich/MagicMirror/maste
### Server Only ### Server Only
In some cases, you want to start the application without an actual app window. In this case, you can start MagicMirror² in server only mode by manually running `node serveronly` or using Docker. This will start the server, after which you can open the application in your browser of choice. Detailed description below. In some cases, you want to start the application without an actual app window. In this case, you can start MagicMirror² in server only mode by manually running `node serveronly` or using Docker. This will start the server, after which you can open the application in your browser of choice. Detailed description below.
### Client Only
When you have a server running remotely and want to connect a standalone client to this instance, you can manually run `node clientonly --address 192.168.1.5 --port 8080`. (Specify the ip address and port number of the server)
**Important:** Make sure that you whitelist the interface/ip in the server config where you want the client to connect to, otherwise it will not be allowed to connect to the server
#### Docker #### Docker
MagicMirror² in server only mode can be deployed using [Docker](https://docker.com). After a successful [Docker installation](https://docs.docker.com/engine/installation/) you just need to execute the following command in the shell: MagicMirror² in server only mode can be deployed using [Docker](https://docker.com). After a successful [Docker installation](https://docs.docker.com/engine/installation/) you just need to execute the following command in the shell:

97
clientonly/index.js Normal file
View File

@ -0,0 +1,97 @@
/* jshint esversion: 6 */
"use strict";
// Use seperate scope to prevent global scope pollution
(function () {
const cookie = require("cookie");
var config = { };
// Parse command line arguments, if any
var addressIndex = process.argv.indexOf("--address");
var portIndex = process.argv.indexOf("--port");
if (addressIndex > -1) {
config.address = process.argv[addressIndex + 1];
} else {
fail();
}
if (portIndex > -1) {
config.port = process.argv[portIndex + 1];
} else {
fail();
}
function fail(message, code = 1) {
if (message !== undefined && typeof message === "string") {
console.log(message);
} else {
console.log("Usage: 'node clientonly --address 192.168.1.10 --port 8080'");
}
process.exit(code);
}
function getServerConfig(url) {
// Return new pending promise
return new Promise((resolve, reject) => {
// Select http or https module, depending on reqested url
const lib = url.startsWith("https") ? require("https") : require("http");
const request = lib.get(url, (response) => {
// Handle http errors
if (response.statusCode < 200 || response.statusCode > 299) {
reject(new Error(`Failed to load page, status code: ${response.statusCode}`));
}
if (response.headers["set-cookie"]) {
response.headers["set-cookie"].forEach(
function (cookiestr) {
if (cookiestr.startsWith("config")) {
var cookieString = JSON.parse(cookie.parse(cookiestr)["config"]);
resolve(cookieString);
}
}
);
};
reject(new Error(`Unable to read config cookie from server (${url}`));
});
// Handle connection errors of the request
request.on("error", (err) => reject(new Error(`Failed to load page, error message: ${err}`)));
})
};
// Only start the client if a non-local server was provided
if (["localhost", "127.0.0.1", "::1", "::ffff:127.0.0.1", undefined].indexOf(config.address) === -1) {
getServerConfig(`http://${config.address}:${config.port}/`)
.then(function (cookieConfig) {
// Pass along the server config via an environment variable
var env = Object.create( process.env );
var options = { env: env };
cookieConfig.address = config.address;
cookieConfig.port = config.port;
env.config = JSON.stringify(cookieConfig);
// Spawn electron application
const electron = require("electron");
const child = require("child_process").spawn(electron, ["js/electron.js"], options );
// Pipe all child process output to current stdout
child.stdout.on("data", function (buf) {
process.stdout.write(`Client: ${buf}`);
});
// Pipe all child process errors to current stderr
child.stderr.on("data", function (buf) {
process.stderr.write(`Client: ${buf}`);
});
child.on("error", function (err) {
process.stdout.write(`Client: ${err}`);
});
})
.catch(function (reason) {
fail(`Unable to connect to server: (${reason})`);
});
} else {
fail();
}
}());

View File

@ -9,6 +9,7 @@
*/ */
var config = { var config = {
address: "localhost",
port: 8080, port: 8080,
ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1"], // Set [] to allow all IP addresses ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1"], // Set [] to allow all IP addresses
// or add a specific IPv4 of 192.168.1.5 : // or add a specific IPv4 of 192.168.1.5 :

View File

@ -8,10 +8,12 @@
*/ */
var port = 8080; var port = 8080;
var address = "localhost";
if (typeof(mmPort) !== "undefined") { if (typeof(mmPort) !== "undefined") {
port = mmPort; port = mmPort;
} }
var defaults = { var defaults = {
address: address,
port: port, port: port,
kioskmode: false, kioskmode: false,
electronOptions: {}, electronOptions: {},

View File

@ -6,7 +6,7 @@ const electron = require("electron");
const core = require(__dirname + "/app.js"); const core = require(__dirname + "/app.js");
// Config // Config
var config = {}; var config = process.env.config ? JSON.parse(process.env.config) : {};
// Module to control application life. // Module to control application life.
const app = electron.app; const app = electron.app;
// Module to create native browser window. // Module to create native browser window.
@ -47,7 +47,7 @@ function createWindow() {
// and load the index.html of the app. // and load the index.html of the app.
//mainWindow.loadURL('file://' + __dirname + '../../index.html'); //mainWindow.loadURL('file://' + __dirname + '../../index.html');
mainWindow.loadURL("http://localhost:" + config.port); mainWindow.loadURL(`http://${config.address}:${config.port}`);
// Open the DevTools if run with "npm start dev" // Open the DevTools if run with "npm start dev"
if (process.argv.includes("dev")) { if (process.argv.includes("dev")) {
@ -96,8 +96,10 @@ app.on("activate", function() {
} }
}); });
// Start the core application. // Start the core application if server is run on localhost
// This starts all node helpers and starts the webserver. // This starts all node helpers and starts the webserver.
if (["localhost", "127.0.0.1", "::1", "::ffff:127.0.0.1", undefined].indexOf(config.address) > -1) {
core.start(function (c) { core.start(function (c) {
config = c; config = c;
}); });
}

View File

@ -62,6 +62,9 @@ var Server = function(config, callback) {
} }
html = html.replace("#CONFIG_FILE#", configFile); html = html.replace("#CONFIG_FILE#", configFile);
// Set a temporary cookie called "config" to the JSON encoded config object
res.cookie("config", JSON.stringify(config));
res.send(html); res.send(html);
}); });

View File

@ -52,6 +52,7 @@
"dependencies": { "dependencies": {
"body-parser": "^1.17.2", "body-parser": "^1.17.2",
"colors": "^1.1.2", "colors": "^1.1.2",
"cookie": "^0.3.1",
"electron": "^1.6.10", "electron": "^1.6.10",
"express": "^4.15.3", "express": "^4.15.3",
"express-ipfilter": "latest", "express-ipfilter": "latest",