mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-12 10:12:11 +03:00
* fix(client): rewrite absolute fetch/EventSource paths under basePath
Absolute browser calls like fetch("/api/...") and new EventSource("/api/...")
do not honor Next.js basePath, so subpath deploys (OMNIROUTE_BASE_PATH) break
dashboard health checks, settings APIs, and SSE unless a reverse proxy rewrites
the domain root.
- Add withBasePath / getDeployBasePath helpers
- Install ref-counted fetch + EventSource rewrite when basePath is set
(same pattern as installDashboardCsrfFetch)
- Mount BasePathNetworkProvider at the root so login works too
- Mirror OMNIROUTE_BASE_PATH to NEXT_PUBLIC_OMNIROUTE_BASE_PATH for the client
- Document in .env.example; unit tests for rewrite rules
* docs(changelog): add fragment for #8515 basePath client fetch
* test(client): move basePath tests into a scanned dir and fix no-op call-shape asserts
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
* fix(client-sweep-8515): restore CHANGELOG #8471 bullet and fix basePath TS2322
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
---------
Co-authored-by: rqzbeh <rqzbeh@users.noreply.github.com>
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
Co-authored-by: Diego Rodrigues de Sa e Souza <diegosouza.pw@gmail.com>
Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
71 lines
2.4 KiB
TypeScript
71 lines
2.4 KiB
TypeScript
/**
|
|
* Client/server helpers for Next.js `basePath` / `OMNIROUTE_BASE_PATH` deploys.
|
|
*
|
|
* Next.js rewrites Link/router automatically, but absolute browser calls like
|
|
* `fetch("/api/...")` and `new EventSource("/api/...")` do not get the prefix.
|
|
* Under a reverse-proxy subpath those hit the domain root instead of the app.
|
|
*/
|
|
|
|
/** Normalize to leading slash, no trailing slash. Empty / root → `""`. */
|
|
export function normalizeBasePath(value?: string | null): string {
|
|
const trimmed = value?.trim() ?? "";
|
|
if (!trimmed || trimmed === "/") return "";
|
|
const withSlash = trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
|
|
return withSlash.replace(/\/+$/, "");
|
|
}
|
|
|
|
/**
|
|
* Deploy basePath as seen by the client bundle.
|
|
* Set via next.config `env.NEXT_PUBLIC_OMNIROUTE_BASE_PATH` from `OMNIROUTE_BASE_PATH`.
|
|
*/
|
|
export function getDeployBasePath(
|
|
env: NodeJS.ProcessEnv = typeof process !== "undefined" ? process.env : ({} as NodeJS.ProcessEnv)
|
|
): string {
|
|
return normalizeBasePath(
|
|
env.NEXT_PUBLIC_OMNIROUTE_BASE_PATH || env.OMNIROUTE_BASE_PATH || ""
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Prefix a same-origin app path with the deploy basePath when needed.
|
|
*
|
|
* - Relative absolute paths: `/api/health/ping` → `/omniroute/api/health/ping`
|
|
* - Absolute same-origin URLs: `https://host/api/x` → `https://host/omniroute/api/x`
|
|
* - Already-prefixed paths, external URLs, and protocol-relative URLs are unchanged
|
|
*/
|
|
export function withBasePath(
|
|
input: string,
|
|
basePath: string = getDeployBasePath(),
|
|
origin?: string
|
|
): string {
|
|
if (!basePath) return input;
|
|
if (!input) return input;
|
|
|
|
// Protocol-relative or non-path forms
|
|
if (input.startsWith("//")) return input;
|
|
|
|
// Absolute path on this origin
|
|
if (input.startsWith("/")) {
|
|
if (input === basePath || input.startsWith(`${basePath}/`)) return input;
|
|
return `${basePath}${input}`;
|
|
}
|
|
|
|
// Absolute URL — only rewrite same-origin
|
|
try {
|
|
const baseOrigin =
|
|
origin ||
|
|
(typeof window !== "undefined" ? window.location.origin : "http://localhost");
|
|
const url = new URL(input, baseOrigin);
|
|
const currentOrigin = new URL(baseOrigin).origin;
|
|
if (url.origin !== currentOrigin) return input;
|
|
|
|
if (url.pathname === basePath || url.pathname.startsWith(`${basePath}/`)) {
|
|
return url.toString();
|
|
}
|
|
url.pathname = `${basePath}${url.pathname.startsWith("/") ? url.pathname : `/${url.pathname}`}`;
|
|
return url.toString();
|
|
} catch {
|
|
return input;
|
|
}
|
|
}
|