From 54853098a7e25573c2d9fd04445a431159d2b4ae Mon Sep 17 00:00:00 2001 From: Bazyli Brzoska Date: Fri, 3 Oct 2025 19:41:42 -0700 Subject: [PATCH 1/6] fix: return an empty object if yaml file is empty --- packages/server/src/utils/traefik/middleware.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/server/src/utils/traefik/middleware.ts b/packages/server/src/utils/traefik/middleware.ts index 4897b94ee..0340f2edb 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}`); From 080233a7cd1e37ce3440dc15814a70d2e6d13157 Mon Sep 17 00:00:00 2001 From: Bazyli Brzoska Date: Sun, 5 Oct 2025 07:54:43 -0700 Subject: [PATCH 2/6] fix: traefik needs middlewares to be empty/valid --- packages/server/src/utils/traefik/application.ts | 8 ++++++++ packages/server/src/utils/traefik/middleware.ts | 10 +++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/server/src/utils/traefik/application.ts b/packages/server/src/utils/traefik/application.ts index b18161c76..ccc4e3f26 100644 --- a/packages/server/src/utils/traefik/application.ts +++ b/packages/server/src/utils/traefik/application.ts @@ -263,6 +263,14 @@ export const writeTraefikConfigRemote = async ( try { const { DYNAMIC_TRAEFIK_PATH } = paths(true); const configPath = path.join(DYNAMIC_TRAEFIK_PATH, `${appName}.yml`); + if (traefikConfig.http?.middlewares) { + // traefik will fail to start if the file contains middlewares entry but no middlewares are defined + const hasNoMiddlewares = Object.keys(traefikConfig.http.middlewares).length === 0; + if (hasNoMiddlewares) { + // if there aren't any middlewares, remove the whole section + delete traefikConfig.http.middlewares; + } + } const yamlStr = stringify(traefikConfig); await execAsyncRemote(serverId, `echo '${yamlStr}' > ${configPath}`); } catch (e) { diff --git a/packages/server/src/utils/traefik/middleware.ts b/packages/server/src/utils/traefik/middleware.ts index 0340f2edb..636b2d367 100644 --- a/packages/server/src/utils/traefik/middleware.ts +++ b/packages/server/src/utils/traefik/middleware.ts @@ -100,9 +100,17 @@ export const loadRemoteMiddlewares = async (serverId: string) => { throw new Error(`File not found: ${configPath}`); } }; -export const writeMiddleware = (config: T) => { +export const writeMiddleware = (config: FileConfig) => { const { DYNAMIC_TRAEFIK_PATH } = paths(); const configPath = join(DYNAMIC_TRAEFIK_PATH, "middlewares.yml"); + 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; + } + } const newYamlContent = stringify(config); writeFileSync(configPath, newYamlContent, "utf8"); }; From e97046c2670d95a8060660dafc9752bf2f91aaf0 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Sun, 5 Oct 2025 17:14:11 +0000 Subject: [PATCH 3/6] [autofix.ci] apply automated fixes --- packages/server/src/utils/traefik/application.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/server/src/utils/traefik/application.ts b/packages/server/src/utils/traefik/application.ts index ccc4e3f26..8e9d7afd7 100644 --- a/packages/server/src/utils/traefik/application.ts +++ b/packages/server/src/utils/traefik/application.ts @@ -265,9 +265,10 @@ export const writeTraefikConfigRemote = async ( const configPath = path.join(DYNAMIC_TRAEFIK_PATH, `${appName}.yml`); if (traefikConfig.http?.middlewares) { // traefik will fail to start if the file contains middlewares entry but no middlewares are defined - const hasNoMiddlewares = Object.keys(traefikConfig.http.middlewares).length === 0; + const hasNoMiddlewares = + Object.keys(traefikConfig.http.middlewares).length === 0; if (hasNoMiddlewares) { - // if there aren't any middlewares, remove the whole section + // if there aren't any middlewares, remove the whole section delete traefikConfig.http.middlewares; } } From 1804a7c30146cf8730b251f5ac7c8236bde1ce41 Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Sun, 5 Oct 2025 11:26:46 -0600 Subject: [PATCH 4/6] refactor: remove unnecessary middleware checks in Traefik config generation --- .../server/src/utils/traefik/application.ts | 9 -------- .../server/src/utils/traefik/middleware.ts | 23 ++++++++++--------- 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/packages/server/src/utils/traefik/application.ts b/packages/server/src/utils/traefik/application.ts index 8e9d7afd7..b18161c76 100644 --- a/packages/server/src/utils/traefik/application.ts +++ b/packages/server/src/utils/traefik/application.ts @@ -263,15 +263,6 @@ export const writeTraefikConfigRemote = async ( try { const { DYNAMIC_TRAEFIK_PATH } = paths(true); const configPath = path.join(DYNAMIC_TRAEFIK_PATH, `${appName}.yml`); - if (traefikConfig.http?.middlewares) { - // traefik will fail to start if the file contains middlewares entry but no middlewares are defined - const hasNoMiddlewares = - Object.keys(traefikConfig.http.middlewares).length === 0; - if (hasNoMiddlewares) { - // if there aren't any middlewares, remove the whole section - delete traefikConfig.http.middlewares; - } - } const yamlStr = stringify(traefikConfig); await execAsyncRemote(serverId, `echo '${yamlStr}' > ${configPath}`); } catch (e) { diff --git a/packages/server/src/utils/traefik/middleware.ts b/packages/server/src/utils/traefik/middleware.ts index 636b2d367..1c412d45a 100644 --- a/packages/server/src/utils/traefik/middleware.ts +++ b/packages/server/src/utils/traefik/middleware.ts @@ -103,14 +103,6 @@ export const loadRemoteMiddlewares = async (serverId: string) => { export const writeMiddleware = (config: FileConfig) => { const { DYNAMIC_TRAEFIK_PATH } = paths(); const configPath = join(DYNAMIC_TRAEFIK_PATH, "middlewares.yml"); - 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; - } - } const newYamlContent = stringify(config); writeFileSync(configPath, newYamlContent, "utf8"); }; @@ -119,6 +111,18 @@ export const createPathMiddlewares = async ( app: ApplicationNested, domain: Domain, ) => { + const { appName } = app; + const { uniqueConfigKey, internalPath, stripPath, path } = domain; + + // Early return if there's no path middleware to create + const needsInternalPathMiddleware = + internalPath && internalPath !== "/" && internalPath !== path; + const needsStripPathMiddleware = stripPath && path && path !== "/"; + + if (!needsInternalPathMiddleware && !needsStripPathMiddleware) { + return; + } + let config: FileConfig; if (app.serverId) { @@ -135,9 +139,6 @@ export const createPathMiddlewares = async ( } } - const { appName } = app; - const { uniqueConfigKey, internalPath, stripPath, path } = domain; - if (!config.http) { config.http = { middlewares: {} }; } 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 5/6] 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 { From 7943c90d5d23613a7c95b22a8ad3ea1c8e4ed051 Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Sun, 5 Oct 2025 12:07:19 -0600 Subject: [PATCH 6/6] refactor: enhance middleware removal logic in Traefik configuration --- packages/server/src/utils/traefik/middleware.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/server/src/utils/traefik/middleware.ts b/packages/server/src/utils/traefik/middleware.ts index c61db23c4..907e65afd 100644 --- a/packages/server/src/utils/traefik/middleware.ts +++ b/packages/server/src/utils/traefik/middleware.ts @@ -195,6 +195,10 @@ export const removePathMiddlewares = async ( } } + if (!config) { + return; + } + const { appName } = app; if (config.http?.middlewares) { @@ -205,13 +209,12 @@ 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 ( + config?.http?.middlewares && + Object.keys(config.http.middlewares).length === 0 + ) { + // if there aren't any middlewares, remove the whole section + delete config.http.middlewares; } // // If http section is empty, remove it completely