/**
|
|
* File: Includes.js
|
|
*
|
|
* Module used for fetching static content for the website
|
|
* like js, css, images, and other static html pages
|
|
*
|
|
* @author Jeffery Russell
|
|
*/
|
|
|
|
const HEADER_KEY = "header";
|
|
|
|
const FOOTER_KEY = "footer";
|
|
|
|
//name of header file
|
|
const HEADER_FILE = "includes/html/header.html";
|
|
|
|
//path of footer file
|
|
const FOOTER_FILE = "includes/html/footer.html";
|
|
|
|
//admin header path
|
|
const ADMIN_HEADER = "includes/html/adminHeader.html";
|
|
|
|
//used for hashing stuff for the header's e-tag for clients cache
|
|
const crypto = require('crypto');
|
|
|
|
|
|
//caching program to make the application run faster
|
|
const cache = require('memory-cache');
|
|
|
|
const fs = require('fs');
|
|
|
|
|
|
const readFile = function(filename)
|
|
{
|
|
return new Promise(function(resolve, reject)
|
|
{
|
|
try
|
|
{
|
|
resolve(fs.readFileSync(filename));
|
|
}
|
|
catch (e)
|
|
{
|
|
console.log(e);
|
|
console.log("Could not find " + filename);
|
|
return("");
|
|
}
|
|
})
|
|
};
|
|
|
|
/**
|
|
* Sends a static file to the client in a way which the web browser
|
|
* caches the contents sent.
|
|
*
|
|
* @param cache -- server's hashmap which reduces file io
|
|
* @param path -- file requested by user
|
|
* @param type -- type of file for the header
|
|
* @param result -- sent to client
|
|
*/
|
|
const sendCachedContent = function(path, type, result)
|
|
{
|
|
const goods = cache.get(path);
|
|
|
|
if(goods == null)
|
|
{
|
|
readFile(path).then(function(content)
|
|
{
|
|
const eTag = crypto.createHash('md5').update(content).digest('hex');
|
|
result.writeHead(200, {'Content-Type': type, 'Cache-Control':
|
|
'public, max-age=2678400', 'ETag': '"' + eTag + '"',
|
|
'Vary': 'Accept-Encoding'});
|
|
result.write(content);
|
|
result.end();
|
|
}).catch(function(error)
|
|
{
|
|
cache.del(path);
|
|
console.log(error);
|
|
});
|
|
}
|
|
else
|
|
{
|
|
const eTag = crypto.createHash('md5').update(goods).digest('hex');
|
|
result.writeHead(200, {'Content-Type': type,
|
|
'Cache-Control': 'public, max-age=2678400',
|
|
'ETag': '"' + eTag + '"',
|
|
'Vary': 'Accept-Encoding'});
|
|
result.write(goods);
|
|
result.end();
|
|
}
|
|
};
|
|
|
|
|
|
module.exports =
|
|
{
|
|
/** Appends the header html section to the result which is
|
|
* sent to the user.
|
|
*
|
|
* @param result
|
|
* @return {*} a promise retrieved from the utils.include function
|
|
*/
|
|
printHeader: function(templateContext)
|
|
{
|
|
return module.exports.includeInObject(HEADER_KEY, templateContext, HEADER_FILE);
|
|
},
|
|
|
|
|
|
includeInObject: function(key, context, fileName)
|
|
{
|
|
return new Promise(function(resolve, reject)
|
|
{
|
|
readFile(fileName).then(function(result)
|
|
{
|
|
context[key] = result;
|
|
resolve();
|
|
}).catch(function(error)
|
|
{
|
|
context[key] = "File Not Found";
|
|
reject(error);
|
|
console.log(error);
|
|
})
|
|
});
|
|
},
|
|
|
|
|
|
/**
|
|
* A function similar to the include statement in PHP
|
|
* This function writes a file to the output
|
|
*
|
|
* @param fileName the file to append to the result
|
|
*/
|
|
include: function(fileName)
|
|
{
|
|
return readFile(fileName);
|
|
},
|
|
|
|
/**
|
|
* Appends the footer to the result object
|
|
*
|
|
* @return {*|Promise}
|
|
*/
|
|
printFooter: function(templateContext)
|
|
{
|
|
return module.exports.includeInObject(FOOTER_KEY, templateContext, FOOTER_FILE);
|
|
},
|
|
|
|
/**
|
|
* Displays the admin header
|
|
*
|
|
* @returns {*|Promise}
|
|
*/
|
|
printAdminHeader(templateContext)
|
|
{
|
|
return module.exports.includeInObject(HEADER_KEY, templateContext, ADMIN_HEADER);
|
|
},
|
|
|
|
|
|
/**Sends a css file to the user
|
|
*
|
|
* @param result
|
|
* @param path
|
|
* @return {*}
|
|
*/
|
|
sendCSS: function(result, path)
|
|
{
|
|
sendCachedContent(path, 'text/css', result);
|
|
},
|
|
|
|
|
|
/**Sends the user an image from the specified fileName.
|
|
*
|
|
* @param result
|
|
* @param fileName
|
|
*/
|
|
sendImage: function(result, fileName)
|
|
{
|
|
sendCachedContent(fileName, 'image/png', result);
|
|
},
|
|
|
|
|
|
/**Sends the user an image from the specified fileName.
|
|
*
|
|
* @param result
|
|
* @param fileName
|
|
*/
|
|
sendJS: function(result, fileName)
|
|
{
|
|
sendCachedContent(fileName, 'application/javascript', result);
|
|
},
|
|
|
|
|
|
/** Might want to change this to be non cached later
|
|
*
|
|
* @param result
|
|
* @param fileName
|
|
*/
|
|
sendPDF: function(result, fileName)
|
|
{
|
|
sendCachedContent(fileName, 'application/pdf', result);
|
|
},
|
|
|
|
|
|
fetchTemplate: function(templateName)
|
|
{
|
|
return readFile("templates/" + templateName);
|
|
},
|
|
|
|
|
|
/**Sends the user an image from the specified fileName.
|
|
*
|
|
* @param result
|
|
* @param fileName
|
|
*/
|
|
sendHTML: function(result, fileName)
|
|
{
|
|
readFile(fileName).then(function(content)
|
|
{
|
|
result.writeHead(200, {'Content-Type': 'text/html'});
|
|
result.write(content);
|
|
result.end();
|
|
}).catch(function(error)
|
|
{
|
|
console.log(error);
|
|
});
|
|
},
|
|
|
|
|
|
/**
|
|
* Sends a svg file to the client.
|
|
*
|
|
* @param result
|
|
* @param fileName
|
|
*/
|
|
sendSVG: function(result, fileName)
|
|
{
|
|
sendCachedContent(fileName, 'image/svg+xml', result);
|
|
},
|
|
|
|
/**
|
|
* Clears the cache
|
|
*/
|
|
clearCache: function()
|
|
{
|
|
console.log("Includes cache cleared");
|
|
cache.clear();
|
|
}
|
|
};
|