mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-31 20:32:20 +03:00
* fix(docker): honor OMNIROUTE_BASE_PATH behind reverse-proxy subpaths Next.js basePath is compile-time state; Docker now records the baked value, forwards the env var as a build-arg, patches root-path images at container start when needed, and probes health under the active subpath. Hard Rule #13: scripts/docker/patch-basepath.sh and the entrypoint invoke Node with a fixed argv; OMNIROUTE_BASE_PATH is read from process.env only — never interpolated into sed/awk. Closes #8600 * fix(docs): unblock CI for Docker basePath guide Describe the build-time basePath marker as a sentinel file instead of a fabricated env var, and replace the unsupported ```env fence with bash so fumadocs/Shiki can compile DOCKER_GUIDE.md during DAST smoke. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(docker): add changelog fragment for #8615 basePath bundle patch Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
87 lines
2.8 KiB
JavaScript
87 lines
2.8 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
/**
|
|
* Compares OMNIROUTE_BASE_PATH at container start against BUILD_OMNIROUTE_BASE_PATH
|
|
* recorded during the image build. When they differ and the image was built for the
|
|
* domain root, rewrites the standalone bundle before Next.js starts.
|
|
*
|
|
* Hard Rule #13: the subpath is read only from process.env (or an injected env
|
|
* object in tests). Never accept it as a CLI argument or interpolate it into a
|
|
* shell sed/awk invocation — see scripts/docker/patch-basepath.sh.
|
|
*/
|
|
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import { pathToFileURL } from "node:url";
|
|
import { normalizeBasePath } from "../build/normalizeBasePath.mjs";
|
|
import { patchStandaloneBasePath } from "./patch-standalone-base-path.mjs";
|
|
|
|
const SENTINEL = "BUILD_OMNIROUTE_BASE_PATH";
|
|
|
|
function readBakedBasePath(appRoot) {
|
|
const sentinelPath = path.join(appRoot, SENTINEL);
|
|
if (!fs.existsSync(sentinelPath)) return "";
|
|
return normalizeBasePath(fs.readFileSync(sentinelPath, "utf8"));
|
|
}
|
|
|
|
function writeBakedBasePath(appRoot, basePath) {
|
|
fs.writeFileSync(path.join(appRoot, SENTINEL), `${basePath}\n`);
|
|
}
|
|
|
|
/**
|
|
* @param {object} [opts]
|
|
* @param {string} [opts.appRoot]
|
|
* @param {NodeJS.ProcessEnv} [opts.env]
|
|
*/
|
|
export function ensureDockerBasePath(opts = {}) {
|
|
const appRoot = opts.appRoot || process.cwd();
|
|
const runtime = normalizeBasePath(opts.env?.OMNIROUTE_BASE_PATH ?? process.env.OMNIROUTE_BASE_PATH);
|
|
const baked = readBakedBasePath(appRoot);
|
|
|
|
if (runtime === baked) {
|
|
return { action: "noop", runtime, baked };
|
|
}
|
|
|
|
if (!runtime && baked) {
|
|
throw new Error(
|
|
`This OmniRoute image was built for subpath ${baked}, but OMNIROUTE_BASE_PATH is unset. ` +
|
|
`Set OMNIROUTE_BASE_PATH=${baked} or rebuild without the build-arg.`
|
|
);
|
|
}
|
|
|
|
const patchResult = patchStandaloneBasePath({
|
|
appRoot,
|
|
fromBasePath: baked,
|
|
toBasePath: runtime,
|
|
});
|
|
writeBakedBasePath(appRoot, runtime);
|
|
return { action: "patched", runtime, baked, patchResult };
|
|
}
|
|
|
|
function main() {
|
|
try {
|
|
const result = ensureDockerBasePath();
|
|
if (result.action === "patched") {
|
|
const { patchResult, runtime } = result;
|
|
console.log(
|
|
`[ensure-docker-base-path] Applied runtime subpath ${runtime} ` +
|
|
`(manifests=${patchResult.patchedManifests}, textFiles=${patchResult.patchedTextFiles})`
|
|
);
|
|
}
|
|
} catch (err) {
|
|
const message = err instanceof Error ? err.message : String(err);
|
|
console.error(`[ensure-docker-base-path] ${message}`);
|
|
console.error(
|
|
"[ensure-docker-base-path] Rebuild the image with the same subpath, e.g.\n" +
|
|
" docker compose build --build-arg OMNIROUTE_BASE_PATH=/omniroute"
|
|
);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
const isEntrypoint =
|
|
Boolean(process.argv[1]) && import.meta.url === pathToFileURL(process.argv[1]).href;
|
|
if (isEntrypoint) {
|
|
main();
|
|
}
|