From 50156ee3f5a2901bb6d0e73a20030a27885854c9 Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Thu, 22 Feb 2024 11:57:31 +0100 Subject: [PATCH] Cherrypick server file --- scripts/server.ts | 112 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 scripts/server.ts diff --git a/scripts/server.ts b/scripts/server.ts new file mode 100644 index 0000000000..8c036721cc --- /dev/null +++ b/scripts/server.ts @@ -0,0 +1,112 @@ +import http from "node:http" + +export class Server { + constructor( + port: number, + options: { + ignorePathPrefix?: string[] + }, + handle: { + mustMatch: string | RegExp + mimetype: string + handle: (path: string) => Promise + }[] + ) { + handle.push({ + mustMatch: "", + mimetype: "text/html", + handle: async () => { + return `Supported endpoints are ` + }, + }) + http.createServer(async (req: http.IncomingMessage, res) => { + try { + console.log( + req.method + " " + req.url, + "from:", + req.headers.origin, + new Date().toISOString() + ) + + const url = new URL(`http://127.0.0.1/` + req.url) + let path = url.pathname + while (path.startsWith("/")) { + path = path.substring(1) + } + if (options?.ignorePathPrefix) { + for (const toIgnore of options.ignorePathPrefix) { + if (path.startsWith(toIgnore)) { + path = path.substring(toIgnore.length + 1) + break + } + } + } + const handler = handle.find((h) => { + if (typeof h.mustMatch === "string") { + return h.mustMatch === path + } + if (path.match(h.mustMatch)) { + return true + } + }) + + if (handler === undefined || handler === null) { + res.writeHead(404, { "Content-Type": "text/html" }) + res.write("

Not found...

") + res.end() + return + } + + res.setHeader( + "Access-Control-Allow-Headers", + "Origin, X-Requested-With, Content-Type, Accept" + ) + res.setHeader("Access-Control-Allow-Origin", req.headers.origin ?? "*") + if (req.method === "OPTIONS") { + res.setHeader( + "Access-Control-Allow-Methods", + "POST, GET, OPTIONS, DELETE, UPDATE" + ) + res.writeHead(204, { "Content-Type": handler.mimetype }) + res.end() + return + } + if (req.method === "POST" || req.method === "UPDATE") { + return + } + + if (req.method === "DELETE") { + return + } + + try { + const result = await handler.handle(path) + res.writeHead(200, { "Content-Type": handler.mimetype }) + res.write(result) + res.end() + } catch (e) { + console.error("Could not handle request:", e) + res.writeHead(500) + res.write(e) + res.end() + } + } catch (e) { + console.error("FATAL:", e) + res.end() + } + }).listen(port) + console.log( + "Server is running on port " + port, + ". Supported endpoints are: " + handle.map((h) => h.mustMatch).join(", ") + ) + } +}