mirror of
https://github.com/MichMich/MagicMirror.git
synced 2025-08-21 12:55:22 +00:00
Release 2.22.0 (#2983)
## [2.22.0] - 2023-01-01 Thanks to: @angeldeejay, @buxxi, @dariom, @dWoolridge, @KristjanESPERANTO, @MagMar94, @naveensrinivasan, @retroflex, @SkySails and @Tom. Special thanks to @khassel, @rejas and @sdetweil for taking over most (if not all) of the work on this release as project collaborators. This version would not be there without their effort. Thank you! ### Added - Added test for remoteFile option in compliments module - Added hourlyWeather functionality to Weather.gov weather provider - Removed weatherEndpoint definition from weathergov.js (not used) - Added css class names "today" and "tomorrow" for default calendar - Added Collaboration.md - Added new github action for dependency review (#2862) - Added a WeatherProvider for Open-Meteo - Added Yr as a weather provider - Added config options "ignoreXOriginHeader" and "ignoreContentSecurityPolicy" ### Removed - Removed usage of internal fetch function of node until it is more stable ### Updated - Cleaned up test directory (#2937) and jest config (#2959) - Wait for all modules to start before declaring the system ready (#2487) - Updated e2e tests (moved `done()` in helper functions) and use es6 syntax in all tests - Updated da translation - Rework weather module - Make sure smhi provider api only gets a maximum of 6 digits coordinates (#2955) - Use fetch instead of XMLHttpRequest in weatherprovider (#2935) - Reworked how weatherproviders handle units (#2849) - Use unix() method for parsing times, fix suntimes on the way (#2950) - Refactor conversion functions into utils class (#2958) - The `cors`-method in `server.js` now supports sending and recieving HTTP headers - Replace `…` by `…` - Cleanup compliments module - Updated dependencies including electron to v22 (#2903) ### Fixed - Correctly show apparent temperature in SMHI weather provider - Ensure updatenotification module isn't shown when local is _ahead_ of remote - Handle node_helper errors during startup (#2944) - Possibility to change FontAwesome class in calendar, so icons like `fab fa-facebook-square` works. - Fix cors problems with newsfeed articles (as far as possible), allow disabling cors per feed with option `useCorsProxy: false` (#2840) - Tests not waiting for the application to start and stop before starting the next test - Fix electron tests failing sometimes in github workflow - Fixed gap in clock module when displayed on the left side with displayType=digital - Fixed playwright issue by upgrading to v1.29.1 (#2969) Signed-off-by: naveen <172697+naveensrinivasan@users.noreply.github.com> Co-authored-by: Karsten Hassel <hassel@gmx.de> Co-authored-by: Malte Hallström <46646495+SkySails@users.noreply.github.com> Co-authored-by: Veeck <github@veeck.de> Co-authored-by: veeck <michael@veeck.de> Co-authored-by: dWoolridge <dwoolridge@charter.net> Co-authored-by: Johan <jojjepersson@yahoo.se> Co-authored-by: Dario Mratovich <dario_mratovich@hotmail.com> Co-authored-by: Dario Mratovich <dario.mratovich@outlook.com> Co-authored-by: Magnus <34011212+MagMar94@users.noreply.github.com> Co-authored-by: Naveen <172697+naveensrinivasan@users.noreply.github.com> Co-authored-by: buxxi <buxxi@omfilm.net> Co-authored-by: Thomas Hirschberger <47733292+Tom-Hirschberger@users.noreply.github.com> Co-authored-by: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Co-authored-by: Andrés Vanegas Jiménez <142350+angeldeejay@users.noreply.github.com>
This commit is contained in:
182
js/server.js
182
js/server.js
@@ -5,136 +5,114 @@
|
||||
* MIT Licensed.
|
||||
*/
|
||||
const express = require("express");
|
||||
const app = require("express")();
|
||||
const path = require("path");
|
||||
const ipfilter = require("express-ipfilter").IpFilter;
|
||||
const fs = require("fs");
|
||||
const helmet = require("helmet");
|
||||
const fetch = require("fetch");
|
||||
|
||||
const Log = require("logger");
|
||||
const Utils = require("./utils.js");
|
||||
const { cors, getConfig, getHtml, getVersion } = require("./server_functions.js");
|
||||
|
||||
/**
|
||||
* Server
|
||||
*
|
||||
* @param {object} config The MM config
|
||||
* @param {Function} callback Function called when done.
|
||||
* @class
|
||||
*/
|
||||
function Server(config, callback) {
|
||||
function Server(config) {
|
||||
const app = express();
|
||||
const port = process.env.MM_PORT || config.port;
|
||||
const serverSockets = new Set();
|
||||
|
||||
let server = null;
|
||||
if (config.useHttps) {
|
||||
const options = {
|
||||
key: fs.readFileSync(config.httpsPrivateKey),
|
||||
cert: fs.readFileSync(config.httpsCertificate)
|
||||
};
|
||||
server = require("https").Server(options, app);
|
||||
} else {
|
||||
server = require("http").Server(app);
|
||||
}
|
||||
const io = require("socket.io")(server, {
|
||||
cors: {
|
||||
origin: /.*$/,
|
||||
credentials: true
|
||||
},
|
||||
allowEIO3: true
|
||||
});
|
||||
|
||||
server.on("connection", (socket) => {
|
||||
serverSockets.add(socket);
|
||||
socket.on("close", () => {
|
||||
serverSockets.delete(socket);
|
||||
});
|
||||
});
|
||||
|
||||
Log.log(`Starting server on port ${port} ... `);
|
||||
|
||||
server.listen(port, config.address || "localhost");
|
||||
|
||||
if (config.ipWhitelist instanceof Array && config.ipWhitelist.length === 0) {
|
||||
Log.warn(Utils.colors.warn("You're using a full whitelist configuration to allow for all IPs"));
|
||||
}
|
||||
|
||||
app.use(function (req, res, next) {
|
||||
ipfilter(config.ipWhitelist, { mode: config.ipWhitelist.length === 0 ? "deny" : "allow", log: false })(req, res, function (err) {
|
||||
if (err === undefined) {
|
||||
res.header("Access-Control-Allow-Origin", "*");
|
||||
return next();
|
||||
}
|
||||
Log.log(err.message);
|
||||
res.status(403).send("This device is not allowed to access your mirror. <br> Please check your config.js or config.js.sample to change this.");
|
||||
});
|
||||
});
|
||||
app.use(helmet(config.httpHeaders));
|
||||
|
||||
app.use("/js", express.static(__dirname));
|
||||
|
||||
const directories = ["/config", "/css", "/fonts", "/modules", "/vendor", "/translations", "/tests/configs"];
|
||||
for (const directory of directories) {
|
||||
app.use(directory, express.static(path.resolve(global.root_path + directory)));
|
||||
}
|
||||
|
||||
app.get("/cors", async function (req, res) {
|
||||
// example: http://localhost:8080/cors?url=https://google.de
|
||||
|
||||
try {
|
||||
const reg = "^/cors.+url=(.*)";
|
||||
let url = "";
|
||||
|
||||
let match = new RegExp(reg, "g").exec(req.url);
|
||||
if (!match) {
|
||||
url = "invalid url: " + req.url;
|
||||
Log.error(url);
|
||||
res.send(url);
|
||||
/**
|
||||
* Opens the server for incoming connections
|
||||
*
|
||||
* @returns {Promise} A promise that is resolved when the server listens to connections
|
||||
*/
|
||||
this.open = function () {
|
||||
return new Promise((resolve) => {
|
||||
if (config.useHttps) {
|
||||
const options = {
|
||||
key: fs.readFileSync(config.httpsPrivateKey),
|
||||
cert: fs.readFileSync(config.httpsCertificate)
|
||||
};
|
||||
server = require("https").Server(options, app);
|
||||
} else {
|
||||
url = match[1];
|
||||
Log.log("cors url: " + url);
|
||||
const response = await fetch(url, { headers: { "User-Agent": "Mozilla/5.0 MagicMirror/" + global.version } });
|
||||
const header = response.headers.get("Content-Type");
|
||||
const data = await response.text();
|
||||
if (header) res.set("Content-Type", header);
|
||||
res.send(data);
|
||||
server = require("http").Server(app);
|
||||
}
|
||||
} catch (error) {
|
||||
Log.error(error);
|
||||
res.send(error);
|
||||
}
|
||||
});
|
||||
const io = require("socket.io")(server, {
|
||||
cors: {
|
||||
origin: /.*$/,
|
||||
credentials: true
|
||||
},
|
||||
allowEIO3: true
|
||||
});
|
||||
|
||||
app.get("/version", function (req, res) {
|
||||
res.send(global.version);
|
||||
});
|
||||
server.on("connection", (socket) => {
|
||||
serverSockets.add(socket);
|
||||
socket.on("close", () => {
|
||||
serverSockets.delete(socket);
|
||||
});
|
||||
});
|
||||
|
||||
app.get("/config", function (req, res) {
|
||||
res.send(config);
|
||||
});
|
||||
Log.log(`Starting server on port ${port} ... `);
|
||||
server.listen(port, config.address || "localhost");
|
||||
|
||||
app.get("/", function (req, res) {
|
||||
let html = fs.readFileSync(path.resolve(`${global.root_path}/index.html`), { encoding: "utf8" });
|
||||
html = html.replace("#VERSION#", global.version);
|
||||
if (config.ipWhitelist instanceof Array && config.ipWhitelist.length === 0) {
|
||||
Log.warn(Utils.colors.warn("You're using a full whitelist configuration to allow for all IPs"));
|
||||
}
|
||||
|
||||
let configFile = "config/config.js";
|
||||
if (typeof global.configuration_file !== "undefined") {
|
||||
configFile = global.configuration_file;
|
||||
}
|
||||
html = html.replace("#CONFIG_FILE#", configFile);
|
||||
app.use(function (req, res, next) {
|
||||
ipfilter(config.ipWhitelist, { mode: config.ipWhitelist.length === 0 ? "deny" : "allow", log: false })(req, res, function (err) {
|
||||
if (err === undefined) {
|
||||
res.header("Access-Control-Allow-Origin", "*");
|
||||
return next();
|
||||
}
|
||||
Log.log(err.message);
|
||||
res.status(403).send("This device is not allowed to access your mirror. <br> Please check your config.js or config.js.sample to change this.");
|
||||
});
|
||||
});
|
||||
|
||||
res.send(html);
|
||||
});
|
||||
app.use(helmet(config.httpHeaders));
|
||||
app.use("/js", express.static(__dirname));
|
||||
|
||||
if (typeof callback === "function") {
|
||||
callback(app, io);
|
||||
}
|
||||
// TODO add tests directory only when running tests?
|
||||
const directories = ["/config", "/css", "/fonts", "/modules", "/vendor", "/translations", "/tests/configs", "/tests/mocks"];
|
||||
for (const directory of directories) {
|
||||
app.use(directory, express.static(path.resolve(global.root_path + directory)));
|
||||
}
|
||||
|
||||
app.get("/cors", async (req, res) => await cors(req, res));
|
||||
|
||||
app.get("/version", (req, res) => getVersion(req, res));
|
||||
|
||||
app.get("/config", (req, res) => getConfig(req, res));
|
||||
|
||||
app.get("/", (req, res) => getHtml(req, res));
|
||||
|
||||
server.on("listening", () => {
|
||||
resolve({
|
||||
app,
|
||||
io
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Closes the server and destroys all lingering connections to it.
|
||||
*
|
||||
* @returns {Promise} A promise that resolves when server has successfully shut down
|
||||
*/
|
||||
this.close = function () {
|
||||
for (const socket of serverSockets.values()) {
|
||||
socket.destroy();
|
||||
}
|
||||
server.close();
|
||||
return new Promise((resolve) => {
|
||||
for (const socket of serverSockets.values()) {
|
||||
socket.destroy();
|
||||
}
|
||||
server.close(resolve);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user