Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ planned for 2025-10-01

Thanks to: @dathbe.

### Added

- Added configuration option for `User-Agent`, used by calendar & news module (#3255)

### Changed

- [clock] Add CSS to prevent line breaking of sunset/sunrise time display (#3816)
Expand Down
3 changes: 1 addition & 2 deletions js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@ const Log = require("logger");
const Server = require(`${__dirname}/server`);
const Utils = require(`${__dirname}/utils`);
const defaultModules = require(`${__dirname}/../modules/default/defaultmodules`);
const { getEnvVarsAsObj } = require(`${__dirname}/server_functions`);

// used to control fetch timeout for node_helpers
const { setGlobalDispatcher, Agent } = require("undici");
const { getEnvVarsAsObj } = require("#server_functions");
// common timeout value, provide environment override in case
const fetch_timeout = process.env.mmFetchTimeout !== undefined ? process.env.mmFetchTimeout : 30000;

Expand Down
2 changes: 1 addition & 1 deletion js/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const ipfilter = require("express-ipfilter").IpFilter;
const helmet = require("helmet");
const socketio = require("socket.io");
const Log = require("logger");
const { cors, getConfig, getHtml, getVersion, getStartup, getEnvVars } = require("./server_functions");
const { cors, getConfig, getHtml, getVersion, getStartup, getEnvVars } = require("#server_functions");

const vendor = require(`${__dirname}/vendor`);

Expand Down
25 changes: 23 additions & 2 deletions js/server_functions.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ async function cors (req, res) {
* @returns {object} An object specifying name and value of the headers.
*/
function getHeadersToSend (url) {
const headersToSend = { "User-Agent": `Mozilla/5.0 MagicMirror/${global.version}` };
const headersToSend = { "User-Agent": getUserAgent() };
const headersToSendMatch = new RegExp("sendheaders=(.+?)(&|$)", "g").exec(url);
if (headersToSendMatch) {
const headers = headersToSendMatch[1].split(",");
Expand Down Expand Up @@ -129,6 +129,27 @@ function getVersion (req, res) {
res.send(global.version);
}

/**
* Gets the preferred `User-Agent`
* @returns {string} `User-Agent` to be used
*/
function getUserAgent () {
const defaultUserAgent = `Mozilla/5.0 (Node.js ${Number(process.version.match(/^v(\d+\.\d+)/)[1])}) MagicMirror/${global.version}`;

if (typeof config === "undefined") {
return defaultUserAgent;
}

switch (typeof config.userAgent) {
case "function":
return config.userAgent();
case "string":
return config.userAgent;
default:
return defaultUserAgent;
}
}

/**
* Gets environment variables needed in the browser.
* @returns {object} environment variables key: values
Expand All @@ -155,4 +176,4 @@ function getEnvVars (req, res) {
res.send(obj);
}

module.exports = { cors, getConfig, getHtml, getVersion, getStartup, getEnvVars, getEnvVarsAsObj };
module.exports = { cors, getConfig, getHtml, getVersion, getStartup, getEnvVars, getEnvVarsAsObj, getUserAgent };
4 changes: 2 additions & 2 deletions modules/default/calendar/calendarfetcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const ical = require("node-ical");
const Log = require("logger");
const NodeHelper = require("node_helper");
const CalendarFetcherUtils = require("./calendarfetcherutils");
const { getUserAgent } = require("#server_functions");
const { scheduleTimer } = require("#module_functions");

/**
Expand Down Expand Up @@ -30,10 +31,9 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEn
const fetchCalendar = () => {
clearTimeout(reloadTimer);
reloadTimer = null;
const nodeVersion = Number(process.version.match(/^v(\d+\.\d+)/)[1]);
let httpsAgent = null;
let headers = {
"User-Agent": `Mozilla/5.0 (Node.js ${nodeVersion}) MagicMirror/${global.version}`
"User-Agent": getUserAgent()
};

if (selfSignedCert) {
Expand Down
4 changes: 2 additions & 2 deletions modules/default/newsfeed/newsfeedfetcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const iconv = require("iconv-lite");
const { htmlToText } = require("html-to-text");
const Log = require("logger");
const NodeHelper = require("node_helper");
const { getUserAgent } = require("#server_functions");
const { scheduleTimer } = require("#module_functions");

/**
Expand Down Expand Up @@ -101,9 +102,8 @@ const NewsfeedFetcher = function (url, reloadInterval, encoding, logFeedWarnings
}
});

const nodeVersion = Number(process.version.match(/^v(\d+\.\d+)/)[1]);
const headers = {
"User-Agent": `Mozilla/5.0 (Node.js ${nodeVersion}) MagicMirror/${global.version}`,
"User-Agent": getUserAgent(),
"Cache-Control": "max-age=0, no-cache, no-store, must-revalidate",
Pragma: "no-cache"
};
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
"imports": {
"#module_functions": {
"default": "./js/module_functions.js"
},
"#server_functions": {
"default": "./js/server_functions.js"
}
},
"main": "js/electron.js",
Expand Down
19 changes: 18 additions & 1 deletion tests/unit/functions/server_functions_spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const { cors } = require("../../../js/server_functions");
const { expect } = require("playwright/test");
const { cors, getUserAgent } = require("#server_functions");

describe("server_functions tests", () => {
describe("The cors method", () => {
Expand Down Expand Up @@ -142,5 +143,21 @@ describe("server_functions tests", () => {
expect(corsResponse.set.mock.calls[2][0]).toBe("header2");
expect(corsResponse.set.mock.calls[2][1]).toBe("value2");
});

it("Gets User-Agent from configuration", async () => {
config = {};
let userAgent;

userAgent = getUserAgent();
expect(userAgent).toContain("Mozilla/5.0 (Node.js ");

config.userAgent = "Mozilla/5.0 (Foo)";
userAgent = getUserAgent();
expect(userAgent).toBe("Mozilla/5.0 (Foo)");

config.userAgent = () => "Mozilla/5.0 (Bar)";
userAgent = getUserAgent();
expect(userAgent).toBe("Mozilla/5.0 (Bar)");
});
});
});