78 lines
2.1 KiB
JavaScript
78 lines
2.1 KiB
JavaScript
import * as fs from "node:fs";
|
|
import { notFoundTemplate } from "../template/4xx.js";
|
|
import { writeHtmlResponse } from "./response.js";
|
|
const VITE_INTERNAL_PREFIXES = [
|
|
"/@vite/",
|
|
"/@fs/",
|
|
"/@id/",
|
|
"/__vite",
|
|
"/@react-refresh",
|
|
"/node_modules/",
|
|
"/.astro/"
|
|
];
|
|
function evaluateRouteGuard(url, acceptHeader, fsInfo) {
|
|
if (!acceptHeader.includes("text/html")) {
|
|
return { action: "next" };
|
|
}
|
|
let pathname;
|
|
try {
|
|
pathname = decodeURI(new URL(url, "http://localhost").pathname);
|
|
} catch {
|
|
return { action: "next" };
|
|
}
|
|
if (VITE_INTERNAL_PREFIXES.some((prefix) => pathname.startsWith(prefix))) {
|
|
return { action: "next" };
|
|
}
|
|
if (url.includes("?")) {
|
|
return { action: "next" };
|
|
}
|
|
if (fsInfo.existsInPublic || fsInfo.existsInSrc) {
|
|
return { action: "next" };
|
|
}
|
|
if (fsInfo.existsAtRootAsFile) {
|
|
return { action: "block", pathname };
|
|
}
|
|
return { action: "next" };
|
|
}
|
|
function routeGuardMiddleware(settings) {
|
|
const { config } = settings;
|
|
return function devRouteGuard(req, res, next) {
|
|
const url = req.url;
|
|
if (!url) {
|
|
return next();
|
|
}
|
|
const accept = req.headers.accept || "";
|
|
let pathname;
|
|
try {
|
|
pathname = decodeURI(new URL(url, "http://localhost").pathname);
|
|
} catch {
|
|
return next();
|
|
}
|
|
const fsInfo = {
|
|
existsInPublic: fs.existsSync(new URL("." + pathname, config.publicDir)),
|
|
existsInSrc: fs.existsSync(new URL("." + pathname, config.srcDir)),
|
|
existsAtRootAsFile: false
|
|
};
|
|
if (accept.includes("text/html") && !url.includes("?") && !VITE_INTERNAL_PREFIXES.some((prefix) => pathname.startsWith(prefix))) {
|
|
try {
|
|
const stat = fs.statSync(new URL("." + pathname, config.root));
|
|
fsInfo.existsAtRootAsFile = stat.isFile();
|
|
} catch {
|
|
}
|
|
}
|
|
const decision = evaluateRouteGuard(url, accept, fsInfo);
|
|
switch (decision.action) {
|
|
case "block": {
|
|
const html = notFoundTemplate(decision.pathname);
|
|
return writeHtmlResponse(res, 404, html);
|
|
}
|
|
case "next":
|
|
return next();
|
|
}
|
|
};
|
|
}
|
|
export {
|
|
evaluateRouteGuard,
|
|
routeGuardMiddleware
|
|
};
|