mirror of https://github.com/openclaw/openclaw.git
52 lines
1.7 KiB
TypeScript
52 lines
1.7 KiB
TypeScript
import { isReadHttpMethod } from "./control-ui-http-utils.js";
|
|
|
|
export type ControlUiRequestClassification =
|
|
| { kind: "not-control-ui" }
|
|
| { kind: "not-found" }
|
|
| { kind: "redirect"; location: string }
|
|
| { kind: "serve" };
|
|
|
|
const ROOT_MOUNTED_GATEWAY_PROBE_PATHS = new Set(["/health", "/healthz", "/ready", "/readyz"]);
|
|
|
|
export function classifyControlUiRequest(params: {
|
|
basePath: string;
|
|
pathname: string;
|
|
search: string;
|
|
method: string | undefined;
|
|
}): ControlUiRequestClassification {
|
|
const { basePath, pathname, search, method } = params;
|
|
if (!basePath) {
|
|
if (pathname === "/ui" || pathname.startsWith("/ui/")) {
|
|
return { kind: "not-found" };
|
|
}
|
|
// Keep core probe routes outside the root-mounted SPA catch-all so the
|
|
// gateway probe handler can answer them even when the Control UI owns `/`.
|
|
if (ROOT_MOUNTED_GATEWAY_PROBE_PATHS.has(pathname)) {
|
|
return { kind: "not-control-ui" };
|
|
}
|
|
// Keep plugin-owned HTTP routes outside the root-mounted Control UI SPA
|
|
// fallback so untrusted plugins cannot claim arbitrary UI paths.
|
|
if (pathname === "/plugins" || pathname.startsWith("/plugins/")) {
|
|
return { kind: "not-control-ui" };
|
|
}
|
|
if (pathname === "/api" || pathname.startsWith("/api/")) {
|
|
return { kind: "not-control-ui" };
|
|
}
|
|
if (!isReadHttpMethod(method)) {
|
|
return { kind: "not-control-ui" };
|
|
}
|
|
return { kind: "serve" };
|
|
}
|
|
|
|
if (!pathname.startsWith(`${basePath}/`) && pathname !== basePath) {
|
|
return { kind: "not-control-ui" };
|
|
}
|
|
if (!isReadHttpMethod(method)) {
|
|
return { kind: "not-control-ui" };
|
|
}
|
|
if (pathname === basePath) {
|
|
return { kind: "redirect", location: `${basePath}/${search}` };
|
|
}
|
|
return { kind: "serve" };
|
|
}
|