feat(frontend): support embedded API prefixes
This commit is contained in:
@@ -15,6 +15,10 @@ describe("resolveBackendUrl", () => {
|
||||
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"])(
|
||||
"rejects any browser-facing backend URL %j",
|
||||
(backendBaseUrl) => {
|
||||
|
||||
@@ -1,6 +1,18 @@
|
||||
export function resolveBackendUrl(value?: string): string {
|
||||
if (value === undefined || value === "/api") return "/api";
|
||||
throw new Error("Invalid backend URL: the browser must use the same-origin /api route");
|
||||
export interface RuntimeConfig {
|
||||
backendBaseUrl?: string;
|
||||
}
|
||||
|
||||
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 {
|
||||
@@ -9,4 +21,6 @@ export function joinBackendPath(base: string, path: string): string {
|
||||
return `${normalizedBase}/${normalizedPath}`;
|
||||
}
|
||||
|
||||
export const backendBaseUrl = resolveBackendUrl();
|
||||
export const backendBaseUrl = resolveBackendUrl(
|
||||
typeof window === "undefined" ? undefined : window.__THOTHII_CONFIG__,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user