Files
OmniRoute/tests/unit/shared/basePath.test.ts
Rouzbeh† 8e5dc0de1b fix(client): rewrite absolute fetch/EventSource paths under basePath (#8515)
* 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>
2026-07-27 21:12:49 -03:00

76 lines
2.3 KiB
TypeScript

import assert from "node:assert/strict";
import { describe, it } from "node:test";
import {
getDeployBasePath,
normalizeBasePath,
withBasePath,
} from "../../../src/shared/utils/basePath";
describe("normalizeBasePath", () => {
it("normalizes leading/trailing slashes", () => {
assert.equal(normalizeBasePath("omniroute"), "/omniroute");
assert.equal(normalizeBasePath("/omniroute/"), "/omniroute");
assert.equal(normalizeBasePath("/omniroute"), "/omniroute");
assert.equal(normalizeBasePath(""), "");
assert.equal(normalizeBasePath("/"), "");
assert.equal(normalizeBasePath(null), "");
});
});
describe("getDeployBasePath", () => {
it("reads NEXT_PUBLIC_OMNIROUTE_BASE_PATH first", () => {
assert.equal(
getDeployBasePath({
NEXT_PUBLIC_OMNIROUTE_BASE_PATH: "/omniroute",
OMNIROUTE_BASE_PATH: "/other",
} as NodeJS.ProcessEnv),
"/omniroute"
);
});
it("falls back to OMNIROUTE_BASE_PATH", () => {
assert.equal(
getDeployBasePath({
OMNIROUTE_BASE_PATH: "/omniroute",
} as NodeJS.ProcessEnv),
"/omniroute"
);
});
});
describe("withBasePath", () => {
const base = "/omniroute";
it("is a no-op when basePath is empty", () => {
assert.equal(withBasePath("/api/health/ping", ""), "/api/health/ping");
});
it("prefixes absolute app paths", () => {
assert.equal(withBasePath("/api/health/ping", base), "/omniroute/api/health/ping");
assert.equal(withBasePath("/v1/models", base), "/omniroute/v1/models");
});
it("does not double-prefix", () => {
assert.equal(withBasePath("/omniroute/api/health/ping", base), "/omniroute/api/health/ping");
assert.equal(withBasePath("/omniroute", base), "/omniroute");
});
it("rewrites same-origin absolute URLs", () => {
assert.equal(
withBasePath("https://host.example/api/x", base, "https://host.example"),
"https://host.example/omniroute/api/x"
);
});
it("leaves external absolute URLs alone", () => {
assert.equal(
withBasePath("https://other.example/api/x", base, "https://host.example"),
"https://other.example/api/x"
);
});
it("leaves protocol-relative URLs alone", () => {
assert.equal(withBasePath("//cdn.example/app.js", base), "//cdn.example/app.js");
});
});