Add an HTTP server for development purposes that replies to requests with both the static resources and on the fly generated pages. This serves the following needs. - Modern module scripts requires an origin supporting CORS policies, which is not supported when pages are read from disk by the browser. - Provide a way for implemting automatic reloading of pages when changes are made to the source files. - Act as the starting point for making interactive features such as comments and analytics.
82 lines
1.8 KiB
TypeScript
82 lines
1.8 KiB
TypeScript
import * as http from "node:http";
|
|
import * as posix from "node:path/posix";
|
|
|
|
function writeResponse(
|
|
response: http.ServerResponse,
|
|
statusCode: number,
|
|
statusMessage: string,
|
|
mimeType: string | undefined,
|
|
content: Buffer,
|
|
suppressContent = false,
|
|
) {
|
|
response.statusCode = statusCode;
|
|
response.statusMessage = statusMessage;
|
|
if (mimeType !== undefined) {
|
|
response.setHeader("Content-Type", mimeType);
|
|
}
|
|
response.setHeader("Content-Length", content.length);
|
|
if (!suppressContent) {
|
|
response.end(content);
|
|
} else {
|
|
response.end();
|
|
}
|
|
};
|
|
|
|
function writeNotFound(response: http.ServerResponse, suppressContent = false) {
|
|
writeResponse(
|
|
response,
|
|
404, "Not Found",
|
|
"text/plain",
|
|
Buffer.from("404 Not Found"),
|
|
suppressContent,
|
|
);
|
|
}
|
|
|
|
function writeBadRequest(response: http.ServerResponse, suppressContent = false) {
|
|
writeResponse(
|
|
response,
|
|
400, "Bad Request",
|
|
"text/plain",
|
|
Buffer.from("400 Bad Request"),
|
|
suppressContent,
|
|
);
|
|
}
|
|
|
|
const extToMimeType = new Map([
|
|
[".js", "text/javascript"],
|
|
[".html", "text/html"],
|
|
[".css", "text/css"],
|
|
]);
|
|
|
|
export function createServer(
|
|
get: (ref: string) => Buffer | undefined
|
|
) {
|
|
const server = http.createServer(
|
|
{
|
|
joinDuplicateHeaders: true,
|
|
// @ts-expect-error missing in type declaration
|
|
rejectNonStandardBodyWrites: true,
|
|
},
|
|
(request, response) => {
|
|
const url = new URL(`http://localhost${request.url}`);
|
|
if (request.method === "GET" || request.method === "HEAD") {
|
|
const content = get(url.pathname);
|
|
const isHead = request.method === "HEAD";
|
|
if (!content) {
|
|
writeNotFound(response, isHead);
|
|
return;
|
|
}
|
|
writeResponse(
|
|
response,
|
|
200, "OK",
|
|
extToMimeType.get(posix.extname(url.pathname)),
|
|
content,
|
|
isHead,
|
|
)
|
|
return;
|
|
}
|
|
writeBadRequest(response);
|
|
},
|
|
);
|
|
return server;
|
|
}
|