54 lines
2.3 KiB
TypeScript
54 lines
2.3 KiB
TypeScript
import { homeRoute } from "./routes/home";
|
|
import { healthRoute } from "./routes/health";
|
|
import { file } from "bun";
|
|
import { join, resolve } from "path";
|
|
|
|
export async function router(request: Request): Promise<Response> {
|
|
const url = new URL(request.url);
|
|
const method = request.method;
|
|
|
|
// Resolve the absolute path to the public directory
|
|
const publicDir = resolve(import.meta.dir, "public");
|
|
|
|
if (method === "GET") {
|
|
// Handle Static Files
|
|
// We handle requests starting with /public/ OR containing an extension (like /style.css)
|
|
if (url.pathname.startsWith("/public/") || url.pathname.includes(".")) {
|
|
// Normalize path: remove /public prefix if present so that
|
|
// /public/style.css and /style.css both map to .../public/style.css
|
|
const relativePath = url.pathname.replace(/^\/public/, "");
|
|
|
|
// Resolve full path
|
|
// We use join with relativePath. If relativePath starts with /, join handles it correctly
|
|
// effectively treating it as a segment.
|
|
// However, to be extra safe with 'resolve', we ensure we are resolving from publicDir.
|
|
// simple join(publicDir, relativePath) is usually enough with 'bun'.
|
|
// But we use 'resolve' to handle .. segments correctly.
|
|
// We prepend '.' to relativePath to ensure it's treated as relative to publicDir logic
|
|
const normalizedRelative = relativePath.startsWith("/") ? "." + relativePath : relativePath;
|
|
const requestedPath = resolve(publicDir, normalizedRelative);
|
|
|
|
// Security Check: Block Path Traversal
|
|
if (requestedPath.startsWith(publicDir)) {
|
|
const staticFile = file(requestedPath);
|
|
if (await staticFile.exists()) {
|
|
return new Response(staticFile);
|
|
}
|
|
} else {
|
|
// If path traversal detected, return 403 or 404.
|
|
// 403 indicates we caught them.
|
|
return new Response("Forbidden", { status: 403 });
|
|
}
|
|
}
|
|
|
|
if (url.pathname === "/" || url.pathname === "/index.html") {
|
|
return homeRoute();
|
|
}
|
|
if (url.pathname === "/health") {
|
|
return healthRoute();
|
|
}
|
|
}
|
|
|
|
return new Response("Not Found", { status: 404 });
|
|
}
|