From fc3fceb858c995fe3755f602ef9d738b695014f4 Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Sun, 5 Oct 2025 12:04:21 -0600 Subject: [PATCH] refactor: improve Traefik middleware configuration handling and validation --- .../server/src/utils/traefik/middleware.ts | 34 +++++++++++++++---- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/packages/server/src/utils/traefik/middleware.ts b/packages/server/src/utils/traefik/middleware.ts index 1c412d45a..c61db23c4 100644 --- a/packages/server/src/utils/traefik/middleware.ts +++ b/packages/server/src/utils/traefik/middleware.ts @@ -76,7 +76,7 @@ export const loadMiddlewares = () => { throw new Error(`File not found: ${configPath}`); } const yamlStr = readFileSync(configPath, "utf8"); - const config = (parse(yamlStr) ?? {}) as T; + const config = parse(yamlStr) as T; return config; }; @@ -94,7 +94,7 @@ export const loadRemoteMiddlewares = async (serverId: string) => { console.error(`Error: ${stderr}`); throw new Error(`File not found: ${configPath}`); } - const config = (parse(stdout) ?? {}) as FileConfig; + const config = parse(stdout) as FileConfig; return config; } catch (_) { throw new Error(`File not found: ${configPath}`); @@ -139,17 +139,19 @@ export const createPathMiddlewares = async ( } } - if (!config.http) { + if (!config) { + config = { http: { middlewares: {} } }; + } else if (!config.http) { config.http = { middlewares: {} }; } - if (!config.http.middlewares) { - config.http.middlewares = {}; + if (!config.http?.middlewares) { + config.http!.middlewares = {}; } // Add internal path prefix middleware if (internalPath && internalPath !== "/" && internalPath !== path) { const middlewareName = `addprefix-${appName}-${uniqueConfigKey}`; - config.http.middlewares[middlewareName] = { + config.http!.middlewares[middlewareName] = { addPrefix: { prefix: internalPath, }, @@ -159,7 +161,7 @@ export const createPathMiddlewares = async ( // Strip external path middleware if needed if (stripPath && path && path !== "/") { const middlewareName = `stripprefix-${appName}-${uniqueConfigKey}`; - config.http.middlewares[middlewareName] = { + config.http!.middlewares[middlewareName] = { stripPrefix: { prefixes: [path], }, @@ -203,6 +205,24 @@ export const removePathMiddlewares = async ( delete config.http.middlewares[stripPrefixMiddleware]; } + if (config?.http?.middlewares) { + // traefik will fail to start if the file contains middlewares entry but no middlewares are defined + const hasNoMiddlewares = Object.keys(config.http.middlewares).length === 0; + if (hasNoMiddlewares) { + // if there aren't any middlewares, remove the whole section + delete config.http.middlewares; + } + } + + // // If http section is empty, remove it completely + if (config?.http && Object.keys(config?.http).length === 0) { + delete config.http; + } + + if (config && Object.keys(config || {}).length === 0) { + config = {}; + } + if (app.serverId) { await writeTraefikConfigRemote(config, "middlewares", app.serverId); } else {