feat(frontend): support embedded API prefixes

This commit is contained in:
User
2026-08-22 16:29:56 +02:00
parent 3d02c5c1ef
commit 5c505d4c85
2 changed files with 22 additions and 4 deletions
+4
View File
@@ -15,6 +15,10 @@ describe("resolveBackendUrl", () => {
expect(backendBaseUrl).toBe("/api"); expect(backendBaseUrl).toBe("/api");
}); });
it("accepts a same-origin prefixed API base for embedded deployments", () => {
expect(resolveBackendUrl({ backendBaseUrl: "/embedded/api" })).toBe("/embedded/api");
});
it.each(["/backend", "api", "//evil.test", "ftp://example.test", "https://user:pass@example.test"])( it.each(["/backend", "api", "//evil.test", "ftp://example.test", "https://user:pass@example.test"])(
"rejects any browser-facing backend URL %j", "rejects any browser-facing backend URL %j",
(backendBaseUrl) => { (backendBaseUrl) => {
+18 -4
View File
@@ -1,6 +1,18 @@
export function resolveBackendUrl(value?: string): string { export interface RuntimeConfig {
if (value === undefined || value === "/api") return "/api"; backendBaseUrl?: string;
throw new Error("Invalid backend URL: the browser must use the same-origin /api route"); }
declare global {
interface Window {
__THOTHII_CONFIG__?: RuntimeConfig;
}
}
export function resolveBackendUrl(value?: string | RuntimeConfig): string {
const candidate = typeof value === "string" ? value : value?.backendBaseUrl;
if (candidate === undefined || candidate === "/api") return "/api";
if (/^\/(?:[A-Za-z0-9._~-]+\/)+api$/.test(candidate)) return candidate;
throw new Error("Invalid backend URL: the browser must use a same-origin API route");
} }
export function joinBackendPath(base: string, path: string): string { export function joinBackendPath(base: string, path: string): string {
@@ -9,4 +21,6 @@ export function joinBackendPath(base: string, path: string): string {
return `${normalizedBase}/${normalizedPath}`; return `${normalizedBase}/${normalizedPath}`;
} }
export const backendBaseUrl = resolveBackendUrl(); export const backendBaseUrl = resolveBackendUrl(
typeof window === "undefined" ? undefined : window.__THOTHII_CONFIG__,
);