diff --git a/src/index.js b/src/index.js
index 20f7d69..62c9cb4 100644
--- a/src/index.js
+++ b/src/index.js
@@ -2,8 +2,8 @@ const http = require("http");
const fs = require("fs");
const cluster = require("./utils/clusterBunShim.js"); // Cluster module with shim for Bun
const sanitizeURL = require("./utils/urlSanitizer.js");
-const generateErrorStack = require("./utils/generateErrorStack.js");
-const serverHTTPErrorDescs = require("./res/httpErrorDescriptions.js");
+//const generateErrorStack = require("./utils/generateErrorStack.js");
+//const serverHTTPErrorDescs = require("./res/httpErrorDescriptions.js");
const getOS = require("./utils/getOS.js");
const svrjsInfo = require("../svrjs.json");
const version = svrjsInfo.version;
@@ -17,26 +17,28 @@ if (!fs.existsSync(__dirname + "/temp")) fs.mkdirSync(__dirname + "/temp");
const serverconsoleConstructor = require("./utils/serverconsole.js");
-let config = {};
+let configJSON = {};
// TODO: configuration from config.json
-let page404 = "404.html"
-let errorPages = [];
-let stackHidden = true;
-let exposeServerVersion = false;
-let exposeModsInErrorPages = false;
-let enableLogging = true;
-let serverAdmin = "webmaster@svrjs.org";
-function getCustomHeaders() {
- return {};
+if (!configJSON.page404) configJSON.page404 = "404.html"
+if (!configJSON.errorPages) configJSON.errorPages = [];
+if (!configJSON.stackHidden) configJSON.stackHidden = true;
+if (!configJSON.exposeServerVersion) configJSON.exposeServerVersion = false;
+if (!configJSON.exposeModsInErrorPages) configJSON.exposeModsInErrorPages = false;
+if (!configJSON.enableLogging) configJSON.enableLogging = true;
+if (!configJSON.serverAdministratorEmail) configJSON.serverAdministratorEmail = "webmaster@svrjs.org";
+
+const serverconsole = serverconsoleConstructor(configJSON.enableLogging);
+
+let middleware = [
+ require("./middleware/core.js")
+];
+
+function addMiddleware(mw) {
+ middleware.push(mw);
}
-const serverconsole = serverconsoleConstructor(enableLogging);
-
function requestHandler(req, res) {
- // TODO: variables from SVR.JS 3.x
- let isProxy = false;
-
let reqIdInt = Math.floor(Math.random() * 16777216);
if (reqIdInt == 16777216) reqIdInt = 0;
const reqId = "0".repeat(6 - reqIdInt.toString(16).length) + reqIdInt.toString(16);
@@ -52,192 +54,39 @@ function requestHandler(req, res) {
locmessage: (msg) => serverconsole.locmessage(msg, reqId)
};
- // Server error calling method
- res.error = (errorCode, extName, stack, ch) => {
- if (typeof errorCode !== "number") {
- throw new TypeError("HTTP error code parameter needs to be an integer.");
- }
+ // SVR.JS configuration object (modified)
+ const config = Object.assign(configJSON);
- // Handle optional parameters
- if (extName && typeof extName === "object") {
- ch = stack;
- stack = extName;
- extName = undefined;
- } else if (typeof extName !== "string" && extName !== null && extName !== undefined) {
- throw new TypeError("Extension name parameter needs to be a string.");
- }
+ let index = 0;
- if (stack && typeof stack === "object" && Object.prototype.toString.call(stack) !== "[object Error]") {
- ch = stack;
- stack = undefined;
- } else if (typeof stack !== "object" && typeof stack !== "string" && stack) {
- throw new TypeError("Error stack parameter needs to be either a string or an instance of Error object.");
- }
-
- // Determine error file
- function getErrorFileName(list, callback, _i) {
-
- function medCallback(p) {
- if (p) callback(p);
+ // Call the next middleware function
+ const next = () => {
+ const currentMiddleware = middleware[index++];
+ if (currentMiddleware) {
+ try {
+ currentMiddleware(req, res, logFacilities, config, next);
+ } catch (err) {
+ if (res.error) res.error(500);
else {
- if (errorCode == 404) {
- fs.access(page404, fs.constants.F_OK, function (err) {
- if (err) {
- fs.access("." + errorCode.toString(), fs.constants.F_OK, function (err) {
- try {
- if (err) {
- callback(errorCode.toString() + ".html");
- } else {
- callback("." + errorCode.toString());
- }
- } catch (err2) {
- res.error(500, err2);
- }
- });
- } else {
- try {
- callback(page404);
- } catch (err2) {
- res.error(500, err2);
- }
- }
- });
- } else {
- fs.access("." + errorCode.toString(), fs.constants.F_OK, function (err) {
- try {
- if (err) {
- callback(errorCode.toString() + ".html");
- } else {
- callback("." + errorCode.toString());
- }
- } catch (err2) {
- res.error(500, err2);
- }
- });
- }
+ res.writeHead(500, "Internal Server Error", {
+ Server: (config.exposeServerVersion ? "SVR.JS/" + version + " (" + getOS() + "; " + (process.isBun ? ("Bun/v" + process.versions.bun + "; like Node.JS/" + process.version) : ("Node.JS/" + process.version)) + ")" : "SVR.JS")
+ });
+ res.end("Error while executing the request handler");
}
}
-
- if (!_i) _i = 0;
- if (_i >= list.length) {
- medCallback(false);
- return;
- }
-
- if (list[_i].scode != errorCode || !(matchHostname(list[_i].host) && ipMatch(list[_i].ip, req.socket ? req.socket.localAddress : undefined))) {
- getErrorFileName(list, callback, _i + 1);
- return;
- } else {
- fs.access(list[_i].path, fs.constants.F_OK, function (err) {
- if (err) {
- getErrorFileName(list, callback, _i + 1);
- } else {
- medCallback(list[_i].path);
- }
+ } else {
+ if (res.error) res.error(404);
+ else {
+ res.writeHead(404, "Not Found", {
+ Server: (config.exposeServerVersion ? "SVR.JS/" + version + " (" + getOS() + "; " + (process.isBun ? ("Bun/v" + process.versions.bun + "; like Node.JS/" + process.version) : ("Node.JS/" + process.version)) + ")" : "SVR.JS")
});
+ res.end("Request handler missing");
}
}
-
- getErrorFileName(errorPages, function (errorFile) {
- // Generate error stack if not provided
- if (Object.prototype.toString.call(stack) === "[object Error]") stack = generateErrorStack(stack);
- if (stack === undefined) stack = generateErrorStack(new Error("Unknown error"));
-
- if (errorCode == 500 || errorCode == 502) {
- //TODO: server logging facilities
- logFacilities.errmessage("There was an error while processing the request!");
- logFacilities.errmessage("Stack:");
- logFacilities.errmessage(stack);
- }
-
- // Hide the error stack if specified
- if (stackHidden) stack = "[error stack hidden]";
-
- // Validate the error code and handle unknown codes
- if (serverHTTPErrorDescs[errorCode] === undefined) {
- res.error(501, extName, stack);
- } else {
- // Process custom headers if provided
- let cheaders = { ...getCustomHeaders(), ...ch };
-
- cheaders["Content-Type"] = "text/html; charset=utf-8";
-
- // Set default Allow header for 405 error if not provided
- if (errorCode == 405 && !cheaders["Allow"]) cheaders["Allow"] = "GET, POST, HEAD, OPTIONS";
-
- // Read the error file and replace placeholders with error information
- fs.readFile(errorFile, function (err, data) {
- try {
- if (err) throw err;
- res.writeHead(errorCode, http.STATUS_CODES[errorCode], cheaders);
- responseEnd(data.toString().replace(/{errorMessage}/g, errorCode.toString() + " " + http.STATUS_CODES[errorCode].replace(/&/g, "&").replace(//g, ">")).replace(/{errorDesc}/g, serverHTTPErrorDescs[errorCode]).replace(/{stack}/g, stack.replace(/&/g, "&").replace(//g, ">").replace(/\r\n/g, "
").replace(/\n/g, "
").replace(/\r/g, "
").replace(/ {2}/g, " ")).replace(/{path}/g, req.url.replace(/&/g, "&").replace(//g, ">")).replace(/{server}/g, "" + ((exposeServerVersion ? "SVR.JS/" + version + " (" + getOS() + "; " + (process.isBun ? ("Bun/v" + process.versions.bun + "; like Node.JS/" + process.version) : ("Node.JS/" + process.version)) + ")" : "SVR.JS") + ((!exposeModsInErrorPages || extName == undefined) ? "" : " " + extName)).replace(/&/g, "&").replace(//g, ">") + ((req.headers.host == undefined || isProxy) ? "" : " on " + String(req.headers.host).replace(/&/g, "&").replace(//g, ">"))).replace(/{contact}/g, serverAdmin.replace(/&/g, "&").replace(//g, ">").replace(/\./g, "[dot]").replace(/@/g, "[at]"))); // Replace placeholders in error response
- } catch (err) {
- let additionalError = 500;
- // Handle additional error cases
- if (err.code == "ENOENT") {
- additionalError = 404;
- } else if (err.code == "ENOTDIR") {
- additionalError = 404; // Assume that file doesn't exist
- } else if (err.code == "EACCES") {
- additionalError = 403;
- } else if (err.code == "ENAMETOOLONG") {
- additionalError = 414;
- } else if (err.code == "EMFILE") {
- additionalError = 503;
- } else if (err.code == "ELOOP") {
- additionalError = 508;
- }
-
- res.writeHead(errorCode, http.STATUS_CODES[errorCode], cheaders);
- res.write(("
{errorDesc}
" + ((additionalError == 404) ? "" : "Additionally, a {additionalError} error occurred while loading an error page.
") + "{server}
").replace(/{errorMessage}/g, errorCode.toString() + " " + http.STATUS_CODES[errorCode].replace(/&/g, "&").replace(//g, ">")).replace(/{errorDesc}/g, serverHTTPErrorDescs[errorCode]).replace(/{stack}/g, stack.replace(/&/g, "&").replace(//g, ">").replace(/\r\n/g, "{errorDesc}
" + ((additionalError == 404) ? "" : "Additionally, a {additionalError} error occurred while loading an error page.
") + "{server}
").replace(/{errorMessage}/g, errorCode.toString() + " " + http.STATUS_CODES[errorCode].replace(/&/g, "&").replace(//g, ">")).replace(/{errorDesc}/g, serverHTTPErrorDescs[errorCode]).replace(/{stack}/g, stack.replace(/&/g, "&").replace(//g, ">").replace(/\r\n/g, "