Files
openclaw/src/plugins/http-route-overlap.ts
2026-03-07 19:55:06 +00:00

45 lines
1.4 KiB
TypeScript

import { canonicalizePathVariant } from "../gateway/security-path.js";
import type { OpenClawPluginHttpRouteMatch } from "./types.js";
type PluginHttpRouteLike = {
path: string;
match: OpenClawPluginHttpRouteMatch;
};
function prefixMatchPath(pathname: string, prefix: string): boolean {
return (
pathname === prefix || pathname.startsWith(`${prefix}/`) || pathname.startsWith(`${prefix}%`)
);
}
export function doPluginHttpRoutesOverlap(
a: Pick<PluginHttpRouteLike, "path" | "match">,
b: Pick<PluginHttpRouteLike, "path" | "match">,
): boolean {
const aPath = canonicalizePathVariant(a.path);
const bPath = canonicalizePathVariant(b.path);
if (a.match === "exact" && b.match === "exact") {
return aPath === bPath;
}
if (a.match === "prefix" && b.match === "prefix") {
return prefixMatchPath(aPath, bPath) || prefixMatchPath(bPath, aPath);
}
const prefixRoute = a.match === "prefix" ? a : b;
const exactRoute = a.match === "exact" ? a : b;
return prefixMatchPath(
canonicalizePathVariant(exactRoute.path),
canonicalizePathVariant(prefixRoute.path),
);
}
export function findOverlappingPluginHttpRoute<
T extends {
path: string;
match: OpenClawPluginHttpRouteMatch;
},
>(routes: readonly T[], candidate: PluginHttpRouteLike): T | undefined {
return routes.find((route) => doPluginHttpRoutesOverlap(route, candidate));
}