UNPKG

am-serv

Version:

AbstractMechanics is a framework developed by Andrew Chamber's small group of side projects called Katana Development. Its meant to have a small small footprint, be easy to use, yet powerfull when developing complex websites, and web-applications.

273 lines (206 loc) 9.59 kB
/*-----------------------------------------------------------------------------------* * ----APPLICATION-HTTP-SERVER---- * * Program: AbstractMechanics * * Developer: Katana Developmenr * * Created On: 15-JUNE-2020 * * ----- ----- ----- ----- ----- ----- ----- * * This is a NodeJS Framework for creating moderatly complex web applications. * *-----------------------------------------------------------------------------------*/ const http = require('http'); const url = require('url'); const path = require('path'); const fs = require('fs'); const events = require('events'); const {on} = require('process'); const ee = new events.EventEmitter(); class ApplicationServer { /** ______________________________________________________________________________________ * @constructor The constructor for this Object can be looked at as a/the 'HTTP-SERVER'. * @memberof ApplicationServer * @param {number} port Example: ['HTTP://localhost:8080/'] <-- port = 8080; * @param {string} approot file for this applications root folder/directory * _______________________________________________________________________________________ ***/ constructor(port, approot) { this.port = port; this.approot = approot; http.createServer(this.onRequest).listen(port); printStuffNicely('ServerCreated', `\nApplication Server Listening on: ${this.port}`,); } /** _______________________________________________ * @method onRequest() * @memberof ApplicationServer * @param {object} request HTTP Request Data * @param {object} response HTTP Response Data * _______________________________________________ ***/ onRequest(request, response) { const parsedRequest = parseHttpRequest(request); switch(request.method.toUpperCase()) { case 'GET': printStuffNicely('GET REQUEST RECIEVED', parsedRequest); let event = 'EventUrl_' + parsedRequest.pathname; let eventCount = ee.listenerCount(event); if(eventCount > 0) ee.emit(event, parsedRequest.contenttype, response); else { event = 'EventDirectory_' + parsedRequest.dirname; eventCount = ee.listenerCount(event); if(eventCount > 0) ee.emit(event, parsedRequest, response); else err_displayStatus(400, response); } break; case 'POST': printStuffNicely('POST REQUEST RECIEVED', parsedRequest); let ev = 'EventForm_' + parsedRequest.pathname; ee.emit(ev, response); break; }; }; formProccess(url, fn, callback) { var event = 'EventForm_' + url; ee.on(event, (response)=> { printStuffNicely('FORM PROC EVENT TRIGGERED'); callback(fn); }) } /** _________________________________________________________________________ * @method url() * @memberof ApplicationServer * @param {string} url choose a url. * @param {string} file choose file to read and serve when url is requested. * _________________________________________________________________________ ***/ url(url, file) { var event = 'EventUrl_' + url; ee.on(event, (contenttype, response) => { printStuffNicely(`URL Event Triggered`, `URl: ${url}`, `FILE: ${file}`); let __fullfilepath = path.join(this.approot, file); if(fs.existsSync) { fs.readFile(__fullfilepath, (err, data) => { response.writeHead(200, contenttype); response.write(data); response.end(); return 0; }); } else err_displayStatus(404, response); }); } /** ____________________________________________________________________ * @method directory() * @memberof ApplicationServer * @param {string} url url to use as a prefix to directories filenames. * @param {string} dir choose a directory to serve files from. * ____________________________________________________________________ ***/ directory(url, dir) { var event = 'EventDirectory_' + url; ee.on(event, (parsedRequest, response) => { console.log('EVENT TRIGGERED DIRECTORY'); var __fullpath = path.join(this.approot, dir, parsedRequest.filename); fs.readFile(__fullpath, (err, data) => { if(err) console.error('ERROR OCCURED WHILE ATTEMPTING TO READ A FILE'); response.writeHead(200, parsedRequest.contenttype); response.write(data); response.end(); }); }); } }//! <--------------------[ EndOfClass ApplicationServer ]--------------------> //? Stand-alone functions not a part of, but used by, the Class: 'ApplicationServer'. //? ================================================================================== /** ---------------------------- * @function parseHttpRequest() * @param {*} req * ---------------------------- **/ function parseHttpRequest(req) { const reqUrl = req.url; const reqPathname = url.parse(reqUrl).pathname; const parsedHttpRequest = { url: reqUrl, method: req.method, pathname: reqPathname, filename: path.basename(reqPathname), dirname: path.dirname(reqPathname), ext: path.extname(reqPathname), contenttype: setContentType(path.extname(reqPathname)), cookies: req.headers.cookie }; return parsedHttpRequest; } /** ----------------------------------------------------------------------------- * @function setContentType() * @param {string} fileExt Part of filename that comes after the dot operator. * --------------------------------------------------------------------------- ***/ function setContentType(fileExt) { switch(fileExt) { case '': return new Object({"Content-Type": "text/html"}); case '.html': return new Object({"Content-Type": "text/html"}); case '.css': return new Object({"Content-Type": "text/css"}); case '.xml': return new Object({"Content-Type": "text/xml"}); case '.txt': return new Object({"Content-Type": "text/plain"}); case '.ico': return new Object({"Content-Type": "image/x-icon"}); case '.jpg': return new Object({"Content-Type": "image/jpeg"}); case '.png': return new Object({"Content-Type": "image/png"}); case '.gif': return new Object({"Content-Type": "image/gif"}); case '.js': return new Object({"Content-Type": "application/javascript"}); case '.pdf': return new Object({"Content-Type": "application/pdf"}); default: console.log('\n\n\t ===| ERROR: setContentType(fileExt) Defaulted out! |===\n\n'); return new Object({"Content-Type": "text/html"}); } } /*** ---------------------------------------------------------------------------- * @param {number} code HTTP Status code * @param {object} response HTTP response object returned during 'HTTP' request. * ----------------------------------------------------------------------------- ***/ function err_displayStatus(code, response) { let __fullpath = path.join(__dirname, `/httpStatusView/http${code}.html`); console.log(`ERROR: HTTP-${code}`); fs.readFile(__fullpath, (err, data) => { response.writeHead(code, {"Content-Type": "text/html"}); response.write(data); response.end(); }); } /** ---------------------------------------------------------------------------- * @function printStuffNicely(); * @param {string} header Prints as Header * @param {any} arguments prints all extra arguments * ---------------------------------------------------------------------------- ***/ function printStuffNicely(header) { let values = Object.values(arguments); console.log(`\n\n\n\t\t===============|| ${header} ||===============`); values.forEach((value, i) => { if(i !== 0) { console.log(value); } }); return 0; }; /* ? ============[ Function & Class Exports ]============ */ module.exports.ApplicationServer = ApplicationServer; module.exports.printStuffNicely = printStuffNicely; module.exports.setContentType = setContentType; module.exports.err_displayStatus = err_displayStatus;