Skip to content

Commit 76da0aa

Browse files
m-idlerrejasveeckkhasselKristjanESPERANTO
authored
Make User-Agent configurable (#3255)
Fixes #3253 Adds a configuration option to overwrite the default `User-Agent` header that is send at least by the calendar and news module. Allows other modules to use the individual user agent as well. The configuration accepts either a string or a function: ``` var config = { ... userAgent: 'Mozilla/5.0 (My User Agent)', ... } ``` or ``` var config = { ... userAgent: () => 'Mozilla/5.0 (My User Agent)', ... } ``` --------- Co-authored-by: Veeck <[email protected]> Co-authored-by: veeck <[email protected]> Co-authored-by: Karsten Hassel <[email protected]> Co-authored-by: Kristjan ESPERANTO <[email protected]>
1 parent 83d15aa commit 76da0aa

File tree

8 files changed

+54
-10
lines changed

8 files changed

+54
-10
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ planned for 2025-10-01
1313

1414
Thanks to: @dathbe.
1515

16+
### Added
17+
18+
- Added configuration option for `User-Agent`, used by calendar & news module (#3255)
19+
1620
### Changed
1721

1822
- [clock] Add CSS to prevent line breaking of sunset/sunrise time display (#3816)

js/app.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@ const Log = require("logger");
99
const Server = require(`${__dirname}/server`);
1010
const Utils = require(`${__dirname}/utils`);
1111
const defaultModules = require(`${__dirname}/../modules/default/defaultmodules`);
12-
const { getEnvVarsAsObj } = require(`${__dirname}/server_functions`);
13-
1412
// used to control fetch timeout for node_helpers
1513
const { setGlobalDispatcher, Agent } = require("undici");
14+
const { getEnvVarsAsObj } = require("#server_functions");
1615
// common timeout value, provide environment override in case
1716
const fetch_timeout = process.env.mmFetchTimeout !== undefined ? process.env.mmFetchTimeout : 30000;
1817

js/server.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const ipfilter = require("express-ipfilter").IpFilter;
77
const helmet = require("helmet");
88
const socketio = require("socket.io");
99
const Log = require("logger");
10-
const { cors, getConfig, getHtml, getVersion, getStartup, getEnvVars } = require("./server_functions");
10+
const { cors, getConfig, getHtml, getVersion, getStartup, getEnvVars } = require("#server_functions");
1111

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

js/server_functions.js

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ async function cors (req, res) {
6969
* @returns {object} An object specifying name and value of the headers.
7070
*/
7171
function getHeadersToSend (url) {
72-
const headersToSend = { "User-Agent": `Mozilla/5.0 MagicMirror/${global.version}` };
72+
const headersToSend = { "User-Agent": getUserAgent() };
7373
const headersToSendMatch = new RegExp("sendheaders=(.+?)(&|$)", "g").exec(url);
7474
if (headersToSendMatch) {
7575
const headers = headersToSendMatch[1].split(",");
@@ -129,6 +129,27 @@ function getVersion (req, res) {
129129
res.send(global.version);
130130
}
131131

132+
/**
133+
* Gets the preferred `User-Agent`
134+
* @returns {string} `User-Agent` to be used
135+
*/
136+
function getUserAgent () {
137+
const defaultUserAgent = `Mozilla/5.0 (Node.js ${Number(process.version.match(/^v(\d+\.\d+)/)[1])}) MagicMirror/${global.version}`;
138+
139+
if (typeof config === "undefined") {
140+
return defaultUserAgent;
141+
}
142+
143+
switch (typeof config.userAgent) {
144+
case "function":
145+
return config.userAgent();
146+
case "string":
147+
return config.userAgent;
148+
default:
149+
return defaultUserAgent;
150+
}
151+
}
152+
132153
/**
133154
* Gets environment variables needed in the browser.
134155
* @returns {object} environment variables key: values
@@ -155,4 +176,4 @@ function getEnvVars (req, res) {
155176
res.send(obj);
156177
}
157178

158-
module.exports = { cors, getConfig, getHtml, getVersion, getStartup, getEnvVars, getEnvVarsAsObj };
179+
module.exports = { cors, getConfig, getHtml, getVersion, getStartup, getEnvVars, getEnvVarsAsObj, getUserAgent };

modules/default/calendar/calendarfetcher.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const ical = require("node-ical");
33
const Log = require("logger");
44
const NodeHelper = require("node_helper");
55
const CalendarFetcherUtils = require("./calendarfetcherutils");
6+
const { getUserAgent } = require("#server_functions");
67
const { scheduleTimer } = require("#module_functions");
78

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

3939
if (selfSignedCert) {

modules/default/newsfeed/newsfeedfetcher.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const iconv = require("iconv-lite");
55
const { htmlToText } = require("html-to-text");
66
const Log = require("logger");
77
const NodeHelper = require("node_helper");
8+
const { getUserAgent } = require("#server_functions");
89
const { scheduleTimer } = require("#module_functions");
910

1011
/**
@@ -101,9 +102,8 @@ const NewsfeedFetcher = function (url, reloadInterval, encoding, logFeedWarnings
101102
}
102103
});
103104

104-
const nodeVersion = Number(process.version.match(/^v(\d+\.\d+)/)[1]);
105105
const headers = {
106-
"User-Agent": `Mozilla/5.0 (Node.js ${nodeVersion}) MagicMirror/${global.version}`,
106+
"User-Agent": getUserAgent(),
107107
"Cache-Control": "max-age=0, no-cache, no-store, must-revalidate",
108108
Pragma: "no-cache"
109109
};

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626
"imports": {
2727
"#module_functions": {
2828
"default": "./js/module_functions.js"
29+
},
30+
"#server_functions": {
31+
"default": "./js/server_functions.js"
2932
}
3033
},
3134
"main": "js/electron.js",

tests/unit/functions/server_functions_spec.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
const { cors } = require("../../../js/server_functions");
1+
const { expect } = require("playwright/test");
2+
const { cors, getUserAgent } = require("#server_functions");
23

34
describe("server_functions tests", () => {
45
describe("The cors method", () => {
@@ -142,5 +143,21 @@ describe("server_functions tests", () => {
142143
expect(corsResponse.set.mock.calls[2][0]).toBe("header2");
143144
expect(corsResponse.set.mock.calls[2][1]).toBe("value2");
144145
});
146+
147+
it("Gets User-Agent from configuration", async () => {
148+
config = {};
149+
let userAgent;
150+
151+
userAgent = getUserAgent();
152+
expect(userAgent).toContain("Mozilla/5.0 (Node.js ");
153+
154+
config.userAgent = "Mozilla/5.0 (Foo)";
155+
userAgent = getUserAgent();
156+
expect(userAgent).toBe("Mozilla/5.0 (Foo)");
157+
158+
config.userAgent = () => "Mozilla/5.0 (Bar)";
159+
userAgent = getUserAgent();
160+
expect(userAgent).toBe("Mozilla/5.0 (Bar)");
161+
});
145162
});
146163
});

0 commit comments

Comments
 (0)