Created the core
- server.js - glob and files script.js and style.css - important folders in respull/4/head
parent
b1f7473441
commit
ab15494347
@ -1 +1,6 @@
|
|||||||
rcn-frontserver
|
rcn-frontserver
|
||||||
|
====
|
||||||
|
|
||||||
|
#About
|
||||||
|
This is the front-web-server of the Raspberry pi Communication network.
|
||||||
|
More details following soon.
|
||||||
|
@ -0,0 +1,45 @@
|
|||||||
|
// -- Functions --
|
||||||
|
|
||||||
|
/**
|
||||||
|
* binds the data for each element
|
||||||
|
*/
|
||||||
|
function bindData(){
|
||||||
|
let mods = $('model');
|
||||||
|
mods.each(function(){
|
||||||
|
let model = $(this);
|
||||||
|
if (model.attr('refresh-interval') != undefined) {
|
||||||
|
bindModelData(model);
|
||||||
|
setInterval(()=> { bindModelData(model) }, model.attr('refresh-interval'));
|
||||||
|
}
|
||||||
|
else bindModelData(model);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function bindModelData(model) {
|
||||||
|
$.get(model.attr('src'), function(data){
|
||||||
|
$('*[model='+model.attr('name')+']').each(function() {
|
||||||
|
let elem = $(this);
|
||||||
|
elem.html(getDataByPath(JSON.parse(data), elem.attr('datapath')));
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the data of an array by accessing the given path-string
|
||||||
|
* @param {JSON-Object} array Contains the data.
|
||||||
|
* @param {String} path The path to the wanted data.
|
||||||
|
* @return {Object} Returns anything that the path points to.
|
||||||
|
*/
|
||||||
|
function getDataByPath(array, path) {
|
||||||
|
let data = array;
|
||||||
|
path.split('.').forEach(function(p){
|
||||||
|
data = data[p];
|
||||||
|
});
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Events --
|
||||||
|
// Define what happens onLoad
|
||||||
|
$(document).ready(function(){
|
||||||
|
bindData();
|
||||||
|
});
|
@ -0,0 +1,202 @@
|
|||||||
|
// requirement
|
||||||
|
const https = require('https'),
|
||||||
|
fs = require('fs'),
|
||||||
|
urlparse = require('url'),
|
||||||
|
{ JSDOM } = require('jsdom'),
|
||||||
|
perfy = require('perfy'),
|
||||||
|
winston = require('winston'),
|
||||||
|
DailyRotateFile = require('winston-daily-rotate-file'),
|
||||||
|
// args
|
||||||
|
args = require('args-parser')(process.argv),
|
||||||
|
// ressources
|
||||||
|
defaultCss = "/glob/style.css",
|
||||||
|
defaultJs = "/glob/script.js",
|
||||||
|
// logging config using winston
|
||||||
|
fileLoggingFormat = winston.format.printf(info => {
|
||||||
|
return `${info.timestamp} ${info.level.toUpperCase()}: ${JSON.stringify(info.message)}`;
|
||||||
|
});
|
||||||
|
consoleLoggingFormat = winston.format.printf(info => {
|
||||||
|
return `${info.timestamp} [${info.level}] ${JSON.stringify(info.message)}`;
|
||||||
|
});
|
||||||
|
loggingFullFormat = winston.format.combine(
|
||||||
|
winston.format.splat(),
|
||||||
|
winston.format.timestamp({
|
||||||
|
format: 'MM-DD HH:mm:ss.SSS'
|
||||||
|
}),
|
||||||
|
fileLoggingFormat
|
||||||
|
),
|
||||||
|
logger = winston.createLogger({
|
||||||
|
level: winston.config.npm.levels,
|
||||||
|
format: loggingFullFormat,
|
||||||
|
transports: [
|
||||||
|
new winston.transports.Console({
|
||||||
|
format: winston.format.combine(
|
||||||
|
winston.format.colorize(),
|
||||||
|
winston.format.splat(),
|
||||||
|
winston.format.timestamp({
|
||||||
|
format: 'YY-MM-DD HH:mm:ss.SSS'
|
||||||
|
}),
|
||||||
|
consoleLoggingFormat
|
||||||
|
),
|
||||||
|
level: args.loglevel || 'info'
|
||||||
|
}),
|
||||||
|
new winston.transports.File({
|
||||||
|
level: 'debug',
|
||||||
|
filename: './.log/rcn-frontserver.log'
|
||||||
|
}),
|
||||||
|
new DailyRotateFile({
|
||||||
|
level: 'verbose',
|
||||||
|
filename: './.log/frontserver-%DATE%.log',
|
||||||
|
datePattern: 'YYYY-MM-DD',
|
||||||
|
zippedArchive: true,
|
||||||
|
maxSize: '32m',
|
||||||
|
maxFiles: '30d'
|
||||||
|
})
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
// serveroptions
|
||||||
|
options = {
|
||||||
|
key: fs.readFileSync('.ssh/key.pem'), // the key-file
|
||||||
|
cert: fs.readFileSync('.ssh/cert.pem') // the certificate-file
|
||||||
|
},
|
||||||
|
port = args.port || 80; // The port of the web server.
|
||||||
|
|
||||||
|
// --- functional declaration part ---
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a server running on port 80 with tls enabled.
|
||||||
|
* @return {boolean} Returns false if the server stopped by error.
|
||||||
|
*/
|
||||||
|
function main() {
|
||||||
|
try {
|
||||||
|
https.createServer(options, function(req, res) {
|
||||||
|
logger.verbose({'msg': 'Received request', 'method': req.method, 'url': req.url});
|
||||||
|
|
||||||
|
perfy.start('response-calculation'); // caluclate the response time
|
||||||
|
let url = urlparse.parse(req.url); // parse the url
|
||||||
|
let path = url.pathname; // set path to the urls pathname
|
||||||
|
logger.debug({msg: 'Got URL by using url package','url': url, 'path': path});
|
||||||
|
|
||||||
|
let [response, mime] = getResponse(path); // get a response for the url path
|
||||||
|
logger.debug({'response-length': response.length, 'mime-type': mime});
|
||||||
|
|
||||||
|
res.writeHead(200, {"Content-Type": mime}); // write the mime as head
|
||||||
|
res.end(response); // write the response
|
||||||
|
let execTime = perfy.end('response-calculation').fullMilliseconds; // get the execution time
|
||||||
|
logger.debug("Response-Time: " + execTime + " ms for " + req.url, "debug"); // log the execution time
|
||||||
|
|
||||||
|
}).listen(port); // server listens on port specified in the parameter
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(error);
|
||||||
|
logger.info("Shutting Down...");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the extension of a file for the given filename.
|
||||||
|
* @param {String} filename The name of the file.
|
||||||
|
* @return {String} A string that represents the file-extension.
|
||||||
|
*/
|
||||||
|
function getExtension(filename) {
|
||||||
|
try {
|
||||||
|
let exts = filename.match(/\.[a-z]+/g); // get the extension by using regex
|
||||||
|
if (exts) return exts[exts.length - 1]; // return the found extension
|
||||||
|
else return null; // return null if no extension could be found
|
||||||
|
} catch (error) {
|
||||||
|
logger.warn(error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string that depends on the path.
|
||||||
|
* @param {String} path Normally a file-name. Depending on the extension, an other root-path is choosen.
|
||||||
|
* @return {String} An Array containing (Either the files content or an error message) and the mime-type.
|
||||||
|
*/
|
||||||
|
function getResponse(path) {
|
||||||
|
logger.verbose({'msg':'calculationg response', 'path': path});
|
||||||
|
try {
|
||||||
|
// get the file extension
|
||||||
|
let extension = getExtension(path);
|
||||||
|
// returns the home-html file if the path is root.
|
||||||
|
if (path == "/") return [fs.readFileSync("./glob/home.html"), "text/html"];
|
||||||
|
// returns the global script or css if the extension is css or js and the root-path is glob.
|
||||||
|
if (path.includes("/glob") && extension == ".css" || getExtension(path) == ".js") {
|
||||||
|
if (extension == ".css") return [fs.readFileSync("." + path), "text/css"];
|
||||||
|
else return [fs.readFileSync("." + path), "text/javascript"];
|
||||||
|
}
|
||||||
|
// test the extension for differend file types.
|
||||||
|
switch (extension) {
|
||||||
|
case '.html':
|
||||||
|
case '.htm':
|
||||||
|
return [formatHtml(fs.readFileSync("./res/html/" + path)), "text/html"];
|
||||||
|
case '.css':
|
||||||
|
return [fs.readFileSync("./res/css/"+path), "text/css"];
|
||||||
|
case '.js':
|
||||||
|
return [fs.readFileSync("./res/scripts/"+path), "text/javascript"];
|
||||||
|
case '.json':
|
||||||
|
return [fs.readFileSync("./res/data/"+path), "text/plain"];
|
||||||
|
// return some images
|
||||||
|
case '.ico':
|
||||||
|
return [fs.readFileSync("./res/img/"+path), "image/x-icon"]
|
||||||
|
case '.jpg':
|
||||||
|
return [fs.readFileSync("./res/img/"+path), "image/jpeg"];
|
||||||
|
case '.png':
|
||||||
|
return [fs.readFileSync("./res/img/"+path), "image/png"];
|
||||||
|
// return some videos
|
||||||
|
case '.mp4':
|
||||||
|
return [fs.readFileSync("./res/vid/"+path), "video/mpeg"];
|
||||||
|
// default return
|
||||||
|
default:
|
||||||
|
// if the extension is not in those above, the access is not allowed.
|
||||||
|
logger.verbose({'msg': 'Illegal request', 'path': path})
|
||||||
|
return ["Not Allowed", "text/plain"];
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(error);
|
||||||
|
return "Error";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats the html string by adding a link to the standard css and to the standard javascript file.
|
||||||
|
* @param {String} htmlstring A string read from an html file or a html document string itself.
|
||||||
|
* @return {String} A html-string that represents a document.
|
||||||
|
*/
|
||||||
|
function formatHtml(htmlstring) {
|
||||||
|
logger.verbose({'msg': 'Formatting HTML', 'htmlstring': htmlstring});
|
||||||
|
try {
|
||||||
|
let dom = new JSDOM(htmlstring); // creates a dom from the html string
|
||||||
|
let document = dom.window.document;
|
||||||
|
let head = document.getElementsByTagName('head')[0]; // gets the documents head
|
||||||
|
let css = document.createElement('link'); // create a link for the css embeding
|
||||||
|
css.setAttribute("rel", "stylesheet");
|
||||||
|
css.setAttribute("type", "text/css");
|
||||||
|
css.setAttribute("href", defaultCss);
|
||||||
|
head.prepend(css); // prepend the link to the head
|
||||||
|
let js = document.createElement('script'); // create a script for js embedding
|
||||||
|
js.setAttribute("type", "text/javascript");
|
||||||
|
js.setAttribute("src", defaultJs);
|
||||||
|
head.prepend(js); // prepend the script to the head
|
||||||
|
let jquery = document.createElement('script'); // create a script for js embedding
|
||||||
|
jquery.setAttribute("type", "text/javascript");
|
||||||
|
jquery.setAttribute("src", "/glob/jquery.js");
|
||||||
|
head.prepend(jquery); // prepend the script to the head
|
||||||
|
return dom.serialize(); // return a string of the document
|
||||||
|
} catch(error) {
|
||||||
|
logger.error(error);
|
||||||
|
return htmlstring;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Executing the main function
|
||||||
|
if (typeof require != 'undefined' && require.main == module) {
|
||||||
|
logger.exceptions.handle(
|
||||||
|
new winston.transports.File({
|
||||||
|
filename: './.log/frontserver-exceptions.log'
|
||||||
|
})
|
||||||
|
);
|
||||||
|
logger.info("Starting up... "); // log the current date so that the logfile is better to read.
|
||||||
|
main();
|
||||||
|
}
|
Loading…
Reference in New Issue