>
This commit is contained in:
@@ -32,5 +32,6 @@ export const config = {
|
||||
appAdminEmail: env.APP_ADMIN_EMAIL?.trim().toLowerCase() ?? "",
|
||||
appAdminPassword: env.APP_ADMIN_PASSWORD ?? "",
|
||||
appMailFrom: env.APP_MAIL_FROM?.trim().toLowerCase() ?? "[email protected]",
|
||||
webDistPath: resolve(process.cwd(), env.WEB_DIST_PATH ?? "../web/dist"),
|
||||
isProduction: (env.NODE_ENV ?? "development") === "production"
|
||||
};
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
import { resolve, sep } from "node:path";
|
||||
import { config } from "./config";
|
||||
|
||||
const frontendRoot = resolve(config.webDistPath);
|
||||
const indexFile = Bun.file(resolve(frontendRoot, "index.html"));
|
||||
|
||||
const noCacheHeaders = {
|
||||
"Cache-Control": "no-cache"
|
||||
};
|
||||
|
||||
const assetCacheHeaders = {
|
||||
"Cache-Control": "public, max-age=31536000, immutable"
|
||||
};
|
||||
|
||||
const toSafePath = (pathname: string): string | null => {
|
||||
const cleaned = pathname.replace(/^\/+/, "");
|
||||
const absolutePath = resolve(frontendRoot, cleaned);
|
||||
|
||||
if (absolutePath !== frontendRoot && !absolutePath.startsWith(`${frontendRoot}${sep}`)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return absolutePath;
|
||||
};
|
||||
|
||||
const fileResponse = (file: Bun.BunFile, headers?: HeadersInit): Response =>
|
||||
new Response(file, {
|
||||
status: 200,
|
||||
headers
|
||||
});
|
||||
|
||||
export const serveFrontendBuild = async (request: Request): Promise<Response> => {
|
||||
const { pathname } = new URL(request.url);
|
||||
|
||||
if (pathname === "/api" || pathname.startsWith("/api/")) {
|
||||
return new Response("Not found", { status: 404 });
|
||||
}
|
||||
|
||||
if (!(await indexFile.exists())) {
|
||||
return new Response("Frontend build not found. Run `bun run build` first.", {
|
||||
status: 503,
|
||||
headers: {
|
||||
"content-type": "text/plain; charset=utf-8"
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (pathname !== "/") {
|
||||
const safePath = toSafePath(pathname);
|
||||
if (!safePath) {
|
||||
return new Response("Not found", { status: 404 });
|
||||
}
|
||||
|
||||
const assetFile = Bun.file(safePath);
|
||||
if (await assetFile.exists()) {
|
||||
return fileResponse(
|
||||
assetFile,
|
||||
pathname.startsWith("/assets/") ? assetCacheHeaders : noCacheHeaders
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return fileResponse(indexFile, noCacheHeaders);
|
||||
};
|
||||
Reference in New Issue
Block a user