Add development HTTP server

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.
This commit is contained in:
Hornwitser 2025-02-02 10:03:55 +01:00
parent f708088ef7
commit 82323c9158
4 changed files with 201 additions and 1 deletions

82
utils/http-server.ts Normal file
View file

@ -0,0 +1,82 @@
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;
}