add missing path / validation

This commit is contained in:
Pallavi Kumari
2025-10-01 13:03:26 +05:30
parent 4cbf3fffb1
commit 8767d20c47

View File

@@ -108,13 +108,13 @@ function validatePathRewriteConfig(
return { isValid: true }; return { isValid: true };
} }
if ((rewritePath && !rewritePathType) || (!rewritePath && rewritePathType)) { if (rewritePathType !== "stripPrefix") {
return { if ((rewritePath && !rewritePathType) || (!rewritePath && rewritePathType)) {
isValid: false, return { isValid: false, error: "Both rewritePath and rewritePathType must be specified together" };
error: "Both rewritePath and rewritePathType must be specified together" }
};
} }
if (!rewritePath || !rewritePathType) { if (!rewritePath || !rewritePathType) {
return { isValid: true }; return { isValid: true };
} }
@@ -146,26 +146,12 @@ function validatePathRewriteConfig(
} }
} }
// Validate path formats for non-regex types
if (pathMatchType !== "regex" && !path.startsWith("/")) {
return {
isValid: false,
error: "Path must start with '/' for exact and prefix matching"
};
}
// Additional validation for stripPrefix // Additional validation for stripPrefix
if (rewritePathType === "stripPrefix") { if (rewritePathType === "stripPrefix") {
if (pathMatchType !== "prefix") { if (pathMatchType !== "prefix") {
logger.warn(`stripPrefix rewrite type is most effective with prefix path matching. Current match type: ${pathMatchType}`); logger.warn(`stripPrefix rewrite type is most effective with prefix path matching. Current match type: ${pathMatchType}`);
} }
// For stripPrefix, rewritePath is optional (can be empty to just strip)
if (rewritePath && !rewritePath.startsWith("/") && rewritePath !== "") {
return {
isValid: false,
error: "stripPrefix rewritePath must start with '/' or be empty"
};
}
} }
return { isValid: true }; return { isValid: true };
@@ -181,6 +167,14 @@ function createPathRewriteMiddleware(
): { middlewares: { [key: string]: any }; chain?: string[] } { ): { middlewares: { [key: string]: any }; chain?: string[] } {
const middlewares: { [key: string]: any } = {}; const middlewares: { [key: string]: any } = {};
if (pathMatchType !== "regex" && !path.startsWith("/")) {
path = `/${path}`;
}
if (rewritePathType !== "regex" && rewritePath !== "" && !rewritePath.startsWith("/")) {
rewritePath = `/${rewritePath}`;
}
switch (rewritePathType) { switch (rewritePathType) {
case "exact": case "exact":
// Replace the path with the exact rewrite path // Replace the path with the exact rewrite path
@@ -260,9 +254,9 @@ function createPathRewriteMiddleware(
prefix: rewritePath prefix: rewritePath
} }
}; };
return { return {
middlewares, middlewares,
chain: [middlewareName, addPrefixMiddlewareName] chain: [middlewareName, addPrefixMiddlewareName]
}; };
} }
} else { } else {
@@ -387,7 +381,7 @@ export async function getTraefikConfig(
if (!validation.isValid) { if (!validation.isValid) {
logger.error(`Invalid path rewrite configuration for resource ${resourceId}: ${validation.error}`); logger.error(`Invalid path rewrite configuration for resource ${resourceId}: ${validation.error}`);
return; return;
} }
resourcesMap.set(mapKey, { resourcesMap.set(mapKey, {
@@ -520,8 +514,8 @@ export async function getTraefikConfig(
}; };
} }
const additionalMiddlewares = const additionalMiddlewares =
config.getRawConfig().traefik.additional_middlewares || []; config.getRawConfig().traefik.additional_middlewares || [];
const routerMiddlewares = [ const routerMiddlewares = [
badgerMiddlewareName, badgerMiddlewareName,
@@ -529,14 +523,14 @@ export async function getTraefikConfig(
]; ];
// Handle path rewriting middleware // Handle path rewriting middleware
if (resource.rewritePath && if (resource.rewritePath &&
resource.path && resource.path &&
resource.pathMatchType && resource.pathMatchType &&
resource.rewritePathType) { resource.rewritePathType) {
// Create a unique middleware name // Create a unique middleware name
const rewriteMiddlewareName = `rewrite-r${resource.resourceId}-${sanitizeForMiddlewareName(key)}`; const rewriteMiddlewareName = `rewrite-r${resource.resourceId}-${sanitizeForMiddlewareName(key)}`;
try { try {
const rewriteResult = createPathRewriteMiddleware( const rewriteResult = createPathRewriteMiddleware(
rewriteMiddlewareName, rewriteMiddlewareName,
@@ -572,7 +566,7 @@ export async function getTraefikConfig(
// Handle custom headers middleware // Handle custom headers middleware
if (resource.headers || resource.setHostHeader) { if (resource.headers || resource.setHostHeader) {
const headersObj: { [key: string]: string } = {}; const headersObj: { [key: string]: string } = {};
if (resource.headers) { if (resource.headers) {
let headersArr: { name: string; value: string }[] = []; let headersArr: { name: string; value: string }[] = [];
try { try {
@@ -668,15 +662,15 @@ export async function getTraefikConfig(
return ( return (
(targets as TargetWithSite[]) (targets as TargetWithSite[])
.filter((target: TargetWithSite) => { .filter((target: TargetWithSite) => {
if (!target.enabled) { if (!target.enabled) {
return false; return false;
} }
// If any sites are online, exclude offline sites // If any sites are online, exclude offline sites
if (anySitesOnline && !target.site.online) { if (anySitesOnline && !target.site.online) {
return false; return false;
} }
if ( if (
target.site.type === "local" || target.site.type === "local" ||
@@ -689,33 +683,33 @@ export async function getTraefikConfig(
) { ) {
return false; return false;
} }
} else if (target.site.type === "newt") { } else if (target.site.type === "newt") {
if ( if (
!target.internalPort || !target.internalPort ||
!target.method || !target.method ||
!target.site.subnet !target.site.subnet
) { ) {
return false; return false;
} }
} }
return true; return true;
}) })
.map((target: TargetWithSite) => { .map((target: TargetWithSite) => {
if ( if (
target.site.type === "local" || target.site.type === "local" ||
target.site.type === "wireguard" target.site.type === "wireguard"
) { ) {
return { return {
url: `${target.method}://${target.ip}:${target.port}` url: `${target.method}://${target.ip}:${target.port}`
}; };
} else if (target.site.type === "newt") { } else if (target.site.type === "newt") {
const ip = const ip =
target.site.subnet!.split("/")[0]; target.site.subnet!.split("/")[0];
return { return {
url: `${target.method}://${ip}:${target.internalPort}` url: `${target.method}://${ip}:${target.internalPort}`
}; };
} }
}) })
// filter out duplicates // filter out duplicates
.filter( .filter(
(v, i, a) => (v, i, a) =>
@@ -729,7 +723,7 @@ export async function getTraefikConfig(
? { ? {
sticky: { sticky: {
cookie: { cookie: {
name: "p_sticky", // TODO: make this configurable via config.yml like other cookies name: "p_sticky", // TODO: make this configurable via config.yml like other cookies
secure: resource.ssl, secure: resource.ssl,
httpOnly: true httpOnly: true
} }
@@ -811,7 +805,7 @@ export async function getTraefikConfig(
!target.internalPort || !target.internalPort ||
!target.site.subnet !target.site.subnet
) { ) {
return false; return false;
} }
} }
return true; return true;
@@ -852,16 +846,16 @@ export async function getTraefikConfig(
function sanitizePath(path: string | null | undefined): string | undefined { function sanitizePath(path: string | null | undefined): string | undefined {
if (!path) return undefined; if (!path) return undefined;
const trimmed = path.trim(); const trimmed = path.trim();
if (!trimmed) return undefined; if (!trimmed) return undefined;
// Preserve path structure for rewriting, only warn if very long // Preserve path structure for rewriting, only warn if very long
if (trimmed.length > 1000) { if (trimmed.length > 1000) {
logger.warn(`Path exceeds 1000 characters: ${trimmed.substring(0, 100)}...`); logger.warn(`Path exceeds 1000 characters: ${trimmed.substring(0, 100)}...`);
return trimmed.substring(0, 1000); return trimmed.substring(0, 1000);
} }
return trimmed; return trimmed;
} }