Skip to content
Open
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Thanks to: @dathbe.

- [calendar] Fixed broken unittest that only broke at 1st of july and 1st of january (#3830)
- [clock] Fixed missing icons when no other modules with icons is loaded (#3834)
- [weather] Add error handling to fetch functions including cors (#3791)

## [2.32.0] - 2025-07-01

Expand Down
19 changes: 11 additions & 8 deletions js/server_functions.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,19 +46,22 @@ async function cors (req, res) {

const headersToSend = getHeadersToSend(req.url);
const expectedReceivedHeaders = geExpectedReceivedHeaders(req.url);

Log.log(`cors url: ${url}`);
const response = await fetch(url, { headers: headersToSend });

for (const header of expectedReceivedHeaders) {
const headerValue = response.headers.get(header);
if (header) res.set(header, headerValue);
const response = await fetch(url, { headers: headersToSend });
if (response.ok) {
for (const header of expectedReceivedHeaders) {
const headerValue = response.headers.get(header);
if (header) res.set(header, headerValue);
}
const data = await response.text();
res.send(data);
} else {
throw new Error(`Response status: ${response.status}`);
}
const data = await response.text();
res.send(data);
}
} catch (error) {
Log.error(error);
Log.error(`Error in CORS request: ${error}`);
res.send(error);
}
}
Expand Down
29 changes: 19 additions & 10 deletions modules/default/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,28 @@ async function performWebRequest (url, type = "json", useCorsProxy = false, requ
requestUrl = url;
request.headers = getHeadersToSend(requestHeaders);
}
const response = await fetch(requestUrl, request);
const data = await response.text();

if (type === "xml") {
return new DOMParser().parseFromString(data, "text/html");
} else {
if (!data || !data.length > 0) return undefined;
try {
const response = await fetch(requestUrl, request);
if (response.ok) {
const data = await response.text();

if (type === "xml") {
return new DOMParser().parseFromString(data, "text/html");
} else {
if (!data || !data.length > 0) return undefined;

const dataResponse = JSON.parse(data);
if (!dataResponse.headers) {
dataResponse.headers = getHeadersFromResponse(expectedResponseHeaders, response);
const dataResponse = JSON.parse(data);
if (!dataResponse.headers) {
dataResponse.headers = getHeadersFromResponse(expectedResponseHeaders, response);
}
return dataResponse;
}
} else {
throw new Error(`Response status: ${response.status}`);
}
return dataResponse;
} catch (error) {
Log.error(`Error fetching data from ${url}: ${error}`);
}
}

Expand Down
54 changes: 26 additions & 28 deletions modules/default/weather/providers/pirateweather.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,38 +22,36 @@ WeatherProvider.register("pirateweather", {
lon: 0
},

fetchCurrentWeather () {
this.fetchData(this.getUrl())
.then((data) => {
if (!data || !data.currently || typeof data.currently.temperature === "undefined") {
// No usable data?
return;
}
async fetchCurrentWeather () {
try {
const data = await this.fetchData(this.getUrl());
if (!data || !data.currently || typeof data.currently.temperature === "undefined") {
throw new Error("No usable data received from Pirate Weather API.");
}

const currentWeather = this.generateWeatherDayFromCurrentWeather(data);
this.setCurrentWeather(currentWeather);
})
.catch(function (request) {
Log.error("Could not load data ... ", request);
})
.finally(() => this.updateAvailable());
const currentWeather = this.generateWeatherDayFromCurrentWeather(data);
this.setCurrentWeather(currentWeather);
} catch (error) {
Log.error("Could not load data ... ", error);
} finally {
this.updateAvailable();
}
},

fetchWeatherForecast () {
this.fetchData(this.getUrl())
.then((data) => {
if (!data || !data.daily || !data.daily.data.length) {
// No usable data?
return;
}
async fetchWeatherForecast () {
try {
const data = await this.fetchData(this.getUrl());
if (!data || !data.daily || !data.daily.data.length) {
throw new Error("No usable data received from Pirate Weather API.");
}

const forecast = this.generateWeatherObjectsFromForecast(data.daily.data);
this.setWeatherForecast(forecast);
})
.catch(function (request) {
Log.error("Could not load data ... ", request);
})
.finally(() => this.updateAvailable());
const forecast = this.generateWeatherObjectsFromForecast(data.daily.data);
this.setWeatherForecast(forecast);
} catch (error) {
Log.error("Could not load data ... ", error);
} finally {
this.updateAvailable();
}
},

// Create a URL from the config and base URL.
Expand Down
3 changes: 2 additions & 1 deletion tests/unit/functions/server_functions_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ describe("server_functions tests", () => {
headers: {
get: fetchResponseHeadersGet
},
text: fetchResponseHeadersText
text: fetchResponseHeadersText,
ok: true
};

fetch = jest.fn();
Expand Down