Personal blog written from scratch using Node.js, Bootstrap, and MySQL. https://jrtechs.net
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

238 lines
5.4 KiB

  1. /**
  2. * File: Includes.js
  3. *
  4. * Module used for fetching static content for the website
  5. * like js, css, images, and other static html pages
  6. *
  7. * @author Jeffery Russell
  8. */
  9. //used for file IO
  10. const utils = require('../utils/utils.js');
  11. const HEADER_KEY = "header";
  12. const FOOTER_KEY = "footer";
  13. //name of header file
  14. const HEADER_FILE = "includes/html/header.html";
  15. //path of footer file
  16. const FOOTER_FILE = "includes/html/footer.html";
  17. //admin header path
  18. const ADMIN_HEADER = "includes/html/adminHeader.html";
  19. //used for hashing stuff for the header's e-tag for clients cache
  20. const crypto = require('crypto');
  21. //caching program to make the application run faster
  22. const cache = require('memory-cache');
  23. const fs = require('fs');
  24. const readFile = function(filename)
  25. {
  26. return new Promise(function(resolve, reject)
  27. {
  28. try
  29. {
  30. resolve(fs.readFileSync(filename));
  31. }
  32. catch (e)
  33. {
  34. console.log(e);
  35. console.log("Could not find " + filename);
  36. return("");
  37. }
  38. })
  39. };
  40. /**
  41. * Sends a static file to the client in a way which the web browser
  42. * caches the contents sent.
  43. *
  44. * @param cache -- server's hashmap which reduces file io
  45. * @param path -- file requested by user
  46. * @param type -- type of file for the header
  47. * @param result -- sent to client
  48. */
  49. const sendCachedContent = function(path, type, result)
  50. {
  51. const goods = cache.get(path);
  52. if(goods == null)
  53. {
  54. readFile(path).then(function(content)
  55. {
  56. const eTag = crypto.createHash('md5').update(content).digest('hex');
  57. result.writeHead(200, {'Content-Type': type, 'Cache-Control':
  58. 'public, max-age=2678400', 'ETag': '"' + eTag + '"',
  59. 'Vary': 'Accept-Encoding'});
  60. result.write(content);
  61. result.end();
  62. }).catch(function(error)
  63. {
  64. cache.del(path);
  65. console.log(error);
  66. });
  67. }
  68. else
  69. {
  70. const eTag = crypto.createHash('md5').update(goods).digest('hex');
  71. result.writeHead(200, {'Content-Type': type,
  72. 'Cache-Control': 'public, max-age=2678400',
  73. 'ETag': '"' + eTag + '"',
  74. 'Vary': 'Accept-Encoding'});
  75. result.write(goods);
  76. result.end();
  77. }
  78. };
  79. module.exports =
  80. {
  81. /** Appends the header html section to the result which is
  82. * sent to the user.
  83. *
  84. * @param result
  85. * @return {*} a promise retrieved from the utils.include function
  86. */
  87. printHeader: function(templateContext)
  88. {
  89. return module.exports.includeInObject(HEADER_KEY, templateContext, HEADER_FILE);
  90. },
  91. includeInObject: function(key, context, fileName)
  92. {
  93. return new Promise(function(resolve, reject)
  94. {
  95. readFile(fileName).then(function(result)
  96. {
  97. console.log(result);
  98. context[key] = result;
  99. resolve();
  100. }).catch(function(error)
  101. {
  102. context[key] = "File Not Found";
  103. reject(error);
  104. console.log(error);
  105. })
  106. });
  107. },
  108. /**
  109. * A function similar to the include statement in PHP
  110. * This function writes a file to the output
  111. *
  112. * @param fileName the file to append to the result
  113. */
  114. include: function(fileName)
  115. {
  116. return readFile(fileName);
  117. },
  118. /**
  119. * Appends the footer to the result object
  120. *
  121. * @return {*|Promise}
  122. */
  123. printFooter: function(templateContext)
  124. {
  125. return module.exports.includeInObject(FOOTER_KEY, templateContext, FOOTER_FILE);
  126. },
  127. /**
  128. * Displays the admin header
  129. *
  130. * @returns {*|Promise}
  131. */
  132. printAdminHeader(templateContext)
  133. {
  134. return module.exports.includeInObject(HEADER_KEY, templateContext, ADMIN_HEADER);
  135. },
  136. /**Sends a css file to the user
  137. *
  138. * @param result
  139. * @param path
  140. * @return {*}
  141. */
  142. sendCSS: function(result, path)
  143. {
  144. sendCachedContent(path, 'text/css', result);
  145. },
  146. /**Sends the user an image from the specified fileName.
  147. *
  148. * @param result
  149. * @param fileName
  150. */
  151. sendImage: function(result, fileName)
  152. {
  153. sendCachedContent(fileName, 'image/png', result);
  154. },
  155. /**Sends the user an image from the specified fileName.
  156. *
  157. * @param result
  158. * @param fileName
  159. */
  160. sendJS: function(result, fileName)
  161. {
  162. sendCachedContent(fileName, 'application/javascript', result);
  163. },
  164. fetchTemplate: function(templateName)
  165. {
  166. return readFile("templates/" + templateName);
  167. },
  168. /**Sends the user an image from the specified fileName.
  169. *
  170. * @param result
  171. * @param fileName
  172. */
  173. sendHTML: function(result, fileName)
  174. {
  175. readFile("." + fileName).then(function(content)
  176. {
  177. result.writeHead(200, {'Content-Type': 'text/html'});
  178. result.write(content);
  179. result.end();
  180. }).catch(function(error)
  181. {
  182. console.log(error);
  183. });
  184. },
  185. /**
  186. * Sends a svg file to the client.
  187. *
  188. * @param result
  189. * @param fileName
  190. */
  191. sendSVG: function(result, fileName)
  192. {
  193. sendCachedContent(fileName, 'image/svg+xml', result);
  194. },
  195. /**
  196. * Clears the cache
  197. */
  198. clearCache: function()
  199. {
  200. console.log("Includes cache cleared");
  201. cache.clear();
  202. }
  203. };