Normalize widget version in URLs

This commit is contained in:
shamoon
2026-04-01 08:00:20 -07:00
parent 0ea5c3fb68
commit af852e748a
16 changed files with 92 additions and 22 deletions

View File

@@ -10,6 +10,7 @@ import { getKubeConfig } from "utils/config/kubernetes";
import * as shvl from "utils/config/shvl";
import kubernetes from "utils/kubernetes/export";
import createLogger from "utils/logger";
import { parseVersionForUrl } from "utils/proxy/api-helpers";
const logger = createLogger("service-helpers");
@@ -113,7 +114,7 @@ export async function servicesFromDocker() {
}
let substitutedVal = substituteEnvironmentVars(containerLabels[label]);
if (value === "widget.version" || /^widgets\[\d+\]\.version$/.test(value)) {
substitutedVal = parseInt(substitutedVal, 10);
substitutedVal = parseVersionForUrl(substitutedVal);
}
shvl.set(constructedService, value, substitutedVal);
}
@@ -590,7 +591,7 @@ export function cleanServiceGroups(groups) {
"vikunja",
].includes(type)
) {
if (version) widget.version = parseInt(version, 10);
widget.version = parseVersionForUrl(version);
}
if (type === "glances") {
if (metric) widget.metric = metric;

View File

@@ -12,6 +12,22 @@ export function formatApiCall(url, args) {
return url.replace(find, replace).replace(find, replace);
}
export function parseVersionForUrl(version, defaultValue = null) {
if (version === undefined || version === null || version === "") {
return defaultValue;
}
if (typeof version === "number") {
return Number.isInteger(version) && version >= 0 ? version : defaultValue;
}
if (typeof version === "string" && /^\d+$/.test(version)) {
return Number(version);
}
return defaultValue;
}
export function getURLSearchParams(widget, endpoint) {
const params = new URLSearchParams({
group: widget.service_group,

View File

@@ -7,6 +7,7 @@ import {
getURLSearchParams,
jsonArrayFilter,
jsonArrayTransform,
parseVersionForUrl,
sanitizeErrorURL,
} from "./api-helpers";
@@ -21,6 +22,20 @@ describe("utils/proxy/api-helpers", () => {
expect(formatApiCall("{a}-{a}-{missing}", { a: "x" })).toBe("x-x-");
});
it("parseVersionForUrl accepts canonical non-negative integers", () => {
expect(parseVersionForUrl("3")).toBe(3);
expect(parseVersionForUrl(4)).toBe(4);
expect(parseVersionForUrl(undefined, 3)).toBe(3);
});
it("parseVersionForUrl rejects non-canonical values", () => {
expect(parseVersionForUrl("3/../../path", 3)).toBe(3);
expect(parseVersionForUrl("1e2", 3)).toBe(3);
expect(parseVersionForUrl("0x10", 3)).toBe(3);
expect(parseVersionForUrl(-1, 3)).toBe(3);
expect(parseVersionForUrl(Number.NaN, 3)).toBe(3);
});
it("getURLSearchParams includes group/service/index and optionally endpoint", () => {
const widget = { service_group: "g", service_name: "s", index: "0" };

View File

@@ -2,7 +2,7 @@ import cache from "memory-cache";
import getServiceWidget from "utils/config/service-helpers";
import createLogger from "utils/logger";
import { asJson, formatApiCall } from "utils/proxy/api-helpers";
import { asJson, formatApiCall, parseVersionForUrl } from "utils/proxy/api-helpers";
import { httpProxy } from "utils/proxy/http";
import widgets from "widgets/widgets";
@@ -56,7 +56,7 @@ async function getApiInfo(serviceWidget, apiName, serviceName) {
const json = asJson(data);
if (json?.data?.[apiName]) {
cgiPath = json.data[apiName].path;
maxVersion = json.data[apiName].maxVersion;
maxVersion = parseVersionForUrl(json.data[apiName].maxVersion);
logger.debug(
`Detected ${serviceWidget.type}: apiName '${apiName}', cgiPath '${cgiPath}', and maxVersion ${maxVersion}`,
);