64 lines
1.8 KiB
JavaScript

import http from "node:http";
import { AsyncLocalStorage } from "node:async_hooks";
import { createRequest } from "./request.js";
import { createResponse } from "./response.js";
import { routeHandler } from "./route.js";
/**
* @typedef {import('./types/http-server.js').HttpServer} HttpServer
* @typedef {import('./types/http-server.js').HttpServerOptions} HttpServerOptions
* @typedef {import('./types/http-server.js').HttpContext} HttpContext
* @typedef {import('./types/http-server.js').HttpRouteMap} HttpRouteMap
*/
/**
* @param {HttpServerOptions} options
* @returns {HttpServer}
*/
export function createServer(options) {
const { routeMap, enableCors } = options;
const ctxStorage = new AsyncLocalStorage();
let serverPort = 3000;
const server = http.createServer((req, res) => {
try {
const url = new URL(`http://${req.headers.host || `localhost:${serverPort}`}${req.url}`);
/** @type {HttpContext} */
const ctx = {
data: null,
req: createRequest(req),
res: createResponse(res),
params: url.searchParams,
local: {}
};
if (enableCors) {
res.setHeaders(
new Headers({
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET,POST,DELETE,UPDATE,PUT,PATCH",
"Access-Control-Allow-Headers": "Content-Type,Accept"
})
);
}
ctxStorage.run(ctx, () =>
routeHandler(url, ctxStorage, routeMap).then(() => {
console.log(`${new Date().toISOString()} Request: ${url.pathname}`);
})
);
} catch (error) {
console.error(error);
}
});
return {
listen(port = 3000, cb) {
serverPort = port;
server.listen(port, cb);
return server;
}
};
}