app.js 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. const http = require('http')
  2. const fsPromises = require('fs').promises
  3. const path = require('path')
  4. const crypto = require('crypto')
  5. const sleep = require('util').promisify(setTimeout)
  6. const argvIndexOfFile = process.argv.indexOf(__filename)
  7. let DATA_INSTANT = parseInt(process.argv[argvIndexOfFile + 1])
  8. if (isNaN(DATA_INSTANT)) {
  9. DATA_INSTANT = 0
  10. }
  11. let SLEEP_TIME = parseInt(process.argv[argvIndexOfFile + 2])
  12. if (isNaN(SLEEP_TIME)) {
  13. SLEEP_TIME = 200
  14. }
  15. let CACHE_MAX_AGE = parseInt(process.argv[argvIndexOfFile + 3])
  16. if (isNaN(CACHE_MAX_AGE)) {
  17. CACHE_MAX_AGE = 0
  18. }
  19. let PORT = parseInt(process.argv[argvIndexOfFile + 4])
  20. if (isNaN(PORT)) {
  21. PORT = 8000
  22. }
  23. function sha384(data) {
  24. const hash = crypto.createHash('sha384')
  25. hash.update(data)
  26. return hash.digest('base64')
  27. }
  28. async function requestListener(req, res) {
  29. let headers = {
  30. 'Content-Type': 'text/html',
  31. }
  32. let pathString = req.url.substr(1)
  33. let page = parseInt(pathString)
  34. if (pathString == '') {
  35. page = 1
  36. }
  37. let content = ''
  38. const jsContent = await fsPromises.readFile(path.resolve(__dirname, '../instantpage.js'))
  39. const jsHash = sha384(jsContent)
  40. if (pathString == 'instantpage.js') {
  41. headers['Content-Type'] = 'text/javascript'
  42. content += jsContent
  43. }
  44. else if (!isNaN(page)) {
  45. await sleep(SLEEP_TIME)
  46. if (CACHE_MAX_AGE) {
  47. headers['Cache-Control'] = `max-age=${CACHE_MAX_AGE}`
  48. }
  49. content += await fsPromises.readFile(path.resolve(__dirname, 'header.html'))
  50. if (DATA_INSTANT) {
  51. content += `<body>`
  52. }
  53. else {
  54. content += `<body data-instant-allow-query-string data-instant-allow-external-links >`
  55. }
  56. dataInstantAttribute = DATA_INSTANT ? `data-instant` : ``
  57. content += `<h1>Page ${page}</h1>`
  58. for (let i = 1; i <= 3; i++) {
  59. if (page != i) {
  60. content += `<a href="/${i}?${Math.random()}" ${dataInstantAttribute}><span>Page ${i}</span></a>`
  61. }
  62. }
  63. content += `<a href="/${page}?${Math.random()}" target="_blank" ${dataInstantAttribute}><span>Opens in a new tab</span></a>`
  64. content += `<a href="/${page}?${Math.random()}#anchor" ${dataInstantAttribute}><span>Other page anchor</span></a>`
  65. content += `<a href="${req.url}#anchor" id="anchor"><span>Same-page anchor</span></a>`
  66. content += `<a href="/${page}?${Math.random()}" data-no-instant><span>Manually blacklisted link</span></a>`
  67. content += `<a href="https://www.google.com/" ${dataInstantAttribute}><span>External link</span></a>`
  68. content += `<a><span>&lt;a&gt; without <code>href</code></span></a>`
  69. content += `<a href="file:///C:/"><span>file: link</span></a>`
  70. let footer = await fsPromises.readFile(path.resolve(__dirname, 'footer.html'))
  71. footer = footer.toString().replace('__HASH__', jsHash)
  72. content += footer
  73. }
  74. res.writeHead(200, headers)
  75. res.write(content)
  76. res.end()
  77. }
  78. http.createServer(requestListener).listen(PORT)