const http = require('http');
const path = require('path');
const fs = require("fs");
const GetFileType = require("./GetFileType/index.js");
/**
* WebServer's options.
* @typedef WebServerOptions
* @type {object}
* @property {object} [options]
* @property {string} [options.directory=./public/] - The directory to load the file.
* @property {boolean} [options.acceptonlyget=true] - Only accepts get request.
* @property {string} [options.errordocument._404=`${__dirname}../assets/def_pages/404.html`] - Html file path to respond on the request methods other than GET.
* @property {string} [options.errordocument._405=`${__dirname}../assets/def_pages/405.html`] - Html file path to respond on not found.
* @property {boolean} [options.useindexhtml=true] - If it's true, returns ./index.html file when requested directory.
* @property {string} [options.rootfile=/index.html] - You can specify a file to load as a top page. (Please specify files in the published directory.)
* @property {Number} [options.port=3000] - Port to host the page.
*/
/**
* Create a WebServer.
* @constructor
* @param {WebServerOptions} [options] - WebServer Options.
* @returns {WebServer}
* @example <caption>Simple example</caption>
* const {WebServer} = require("lite-web-server");
* var server = new WebServer();
*
* server.start();
*/
class WebServer {
constructor(opts) {
async function run(opts) {
this.opts = opts;
if (opts) {
var error_doc404 = opts.errordocument._404 || `${__dirname}../assets/def_pages/404.html`;
var error_doc405 = opts.errordocument._405 || `${__dirname}../assets/def_pages/405.html`;
try {
var _404 = await fs.readFileSync(error_doc404);
} catch (error) {
console.error(new Error(`Invailed 404 error file location "${error_doc404}". Default location will used.`));
opts.errordocument._404 = `${__dirname}../assets/def_pages/404.html`;
}
try {
var _405 = await fs.readFileSync(error_doc405);
} catch (error) {
console.error(new Error(`Invailed 405 error file location "${error_doc405}". Default location will used.`));
opts.errordocument._405 = `${__dirname}../assets/def_pages/405.html`;
}
}
}
}
/**
* @returns {Promise<Object | null>}
*/
start() {
var _this = this;
return new Promise(async function (resolve, reject) {
var opt = _this.opts;
if (!opt) {
var options = {
directory: "./public",
//notfound: `<!DOCTYPE html>\n<html>\n<head>\n<title>404 Not Found</title>\n</head>\n<body>\n<center>\n<h1>404 Not Found</h1>\n</center>\n<hr>\n<center>Node.js lite-web-server</center>\n</body>\n</html>`,
port: 3000,
acceptonlyget: true,
useindexhtml: true,
rootfile: "/index.html",
//req405error: `<!DOCTYPE html>\n<html>\n<head>\n<title>405 Method Not Allowed</title>\n</head>\n<body>\n<center>\n<h1>405 Method Not Allowed</h1>\n</center>\n<hr>\n<center>Node.js lite-web-server</center>\n</body>\n</html>`,
errordocument: {
_404: `${__dirname}../assets/def_pages/404.html`,
_405: `${__dirname}../assets/def_pages/405.html`
}
}
} else {
var _dir = opt.dir || opt.directory || "./public";
if (_dir == "/") {
var __dir = ".";
} else if (_dir.endsWith("/")) {
var __dir = _dir.slice(0, -1);
} else {
var __dir = _dir;
}
if (__dir.startsWith("/")) {
var dir = "." + __dir;
} else {
var dir = __dir;
}
if (opt.acceptonlyget === false) {
var acceptonlyget = false;
} else {
var acceptonlyget = true;
}
if (opt.useindexhtml === false) {
var useindexhtml = false;
} else {
var useindexhtml = true;
}
var options = {
directory: dir || "./public",
//notfound: opt.notfound || `<!DOCTYPE html>\n<html>\n<head>\n<title>404 Not Found</title>\n</head>\n<body>\n<center>\n<h1>404 Not Found</h1>\n</center>\n<hr>\n<center>Node.js lite-web-server</center>\n</body>\n</html>`,
port: opt.port || 3000,
acceptonlyget: acceptonlyget,
useindexhtml: useindexhtml,
rootfile: opt.rootfile || "/index.html",
//req405error: opt.req405error || `<!DOCTYPE html>\n<html>\n<head>\n<title>405 Method Not Allowed</title>\n</head>\n<body>\n<center>\n<h1>405 Method Not Allowed</h1>\n</center>\n<hr>\n<center>Node.js lite-web-server</center>\n</body>\n</html>`,
errordocument: {
_404: options.errordocument._404 || `${__dirname}../assets/def_pages/404.html`,
_405: options.errordocument._405 || `${__dirname}../assets/def_pages/405.html`
}
}
}
try {
var dir = await fs.readdirSync(options.directory);
} catch (error) {
reject(new Error(`Please create directory "${options.directory}" first.`));
return;
}
try {
var httpserver = http.createServer(async function (req, res) {
if (!(req.method.toUpperCase() == "GET")&&options.acceptonlyget == true) {
try {
var read_file = await fs.readFileSync(options.errordocument._405).toString();
res.writeHead(405, { "Content-Type": "text/html" });
return res.end(read_file);
} catch (error) {
res.writeHead(500, { "Content-Type": "text/html" });
return res.end("<center><h1>Internal Server Error</h1></center>");
}
}
var url = req.url;
//console.log(url);
if (url == "/") {
var filedir = `${options.directory}${options.rootfile}`;
} else if (url.endsWith("/")&&options.useindexhtml) {
var filedir = `${options.directory}${url}index.html`;
} else {
var filedir = `${options.directory}${url}`;
}
try {
var httpcontent = (await GetFileType(filedir.toString())) || "text/plain";
var file = await fs.readFileSync(filedir);
res.writeHead(200, { "Content-Type": httpcontent });
res.end(file);
} catch (error) {
try {
var read_file = await fs.readFileSync(options.errordocument._404).toString();
var file = read_file.replace(/<!--${404URL}-->/g, `${url}`);
res.writeHead(404, { "Content-Type": "text/html" });
res.end(options.notfound);
} catch (error) {
res.writeHead(500, { "Content-Type": "text/html" });
res.end("<center><h1>Internal Server Error</h1></center>");
}
//console.log(error)
}
//fs.Dir.readSync(options.directory+url)
//console.log(options.directory)
}).listen(options.port);
_this.running = httpserver;
_this.started = true;
resolve(httpserver);
} catch (error) {
reject(new Error(error));
}
});
}
}
module.exports = WebServer
Source