Add favicons.zip handling
authorNick Downing <downing.nick@gmail.com>
Sun, 7 Oct 2018 12:12:49 +0000 (23:12 +1100)
committerNick Downing <downing.nick@gmail.com>
Sun, 7 Oct 2018 12:12:49 +0000 (23:12 +1100)
ndserver.js
package.json

index 2243298..762aaa0 100755 (executable)
@@ -9,12 +9,15 @@ let https = require('https')
 let jstemplate = require('jstemplate')
 let less = require('less/lib/less-node')
 let querystring = require('querystring')
+var stream_buffers = require('stream-buffers')
+let yauzl = require('yauzl')
 let util = require('util')
 let url = require('url')
 let zetjs = require('zetjs')
 
-let readFileAsync = util.promisify(fs.readFile)
-let statAsync = util.promisify(fs.stat)
+let fs_readFile = util.promisify(fs.readFile)
+let fs_stat = util.promisify(fs.stat)
+let yauzl_open = util.promisify(yauzl.open)
 
 let build_cache_js = new BuildCache()
 let req_js = async path => {
@@ -32,7 +35,7 @@ let req_json = async path => {
   let result = await build_cache_json.get(path)
   if (result === undefined) {
     console.log('parsing', path)
-    result = JSON.parse(await readFileAsync(path))
+    result = JSON.parse(await fs_readFile(path))
     build_cache_json.set(path, result)
   }
   return result
@@ -44,7 +47,7 @@ let req_less = async (path, site_root, dir_name) => {
   if (result === undefined) {
     console.log('compiling', path)
     let render = await less.render(
-      await readFileAsync(path, {encoding: 'utf-8'}),
+      await fs_readFile(path, {encoding: 'utf-8'}),
       {
         //color: true,
         //compress: false,
@@ -78,12 +81,59 @@ let req_text = async path => {
   let result = await build_cache_text.get(path)
   if (result === undefined) {
     console.log('reading', path)
-    result = await readFileAsync(path, {encoding: 'utf-8'})
+    result = await fs_readFile(path, {encoding: 'utf-8'})
     build_cache_text.set(path, result)
   }
   return result
 }
 
+let build_cache_zip = new BuildCache()
+let req_zip = async path => {
+  let result = await build_cache_zip.get(path)
+  if (result === undefined) {
+    console.log('decompressing', path)
+    result = {}
+    let zipfile = await yauzl_open(path, {autoClose: false})
+    let entries = []
+    await new Promise(
+      (resolve, reject) => {
+        zipfile.
+        on('entry', entry => {entries.push(entry)}).
+        on('end', () => resolve())
+      }
+    )
+    for (let i = 0; i < entries.length; ++i) {
+      let read_stream = await new Promise(
+        (resolve, reject) => {
+          zipfile.openReadStream(
+            entries[i],
+            (err, stream) => {
+              if (err)
+                reject(err)
+              resolve(stream)
+            }
+          )
+        }
+      )
+      let write_stream = new stream_buffers.WritableStreamBuffer()
+      let data = new Promise(
+        (resolve, reject) => {
+          write_stream.
+          on('finish', () => {resolve(write_stream.getContents())}).
+          on('error', () => {reject()})
+        }
+      )
+      read_stream.pipe(write_stream)
+      data = await data
+      console.log('entry path', entries[i].fileName, 'size', data.length)
+      result[entries[i].fileName] = data
+    }
+    await zipfile.close()
+    build_cache_zip.set(path, result)
+  }
+  return result
+}
+
 let build_cache_zet = new BuildCache()
 let req_zet = async path => {
   let result = await build_cache_zet.get(path)
@@ -191,7 +241,7 @@ let app = async (req, res, protocol) => {
   // path elements must be findable in the file system (thus can't be empty)
   let dir_name = ''
   let dir_name_is_pub = false
-  for (var i = 1; i < path.length - 1; ++i) {
+  for (let i = 1; i < path.length - 1; ++i) {
     dir_name += '/' + path[i]
     if (path[i].length === 0 || path[i].charAt(0) === '.') {
       console.log(site, 'bad path component', dir_name)
@@ -199,7 +249,7 @@ let app = async (req, res, protocol) => {
     }
     let stats
     try {
-      stats = await statAsync(site_root + dir_name)
+      stats = await fs_stat(site_root + dir_name)
     }
     catch (err) {
       if (err.code !== 'ENOENT')
@@ -207,7 +257,7 @@ let app = async (req, res, protocol) => {
       if (!dir_name_is_pub) {
         temp = dir_name + '.pub'
         try {
-          stats = await statAsync(site_root + temp)
+          stats = await fs_stat(site_root + temp)
           dir_name = temp
           dir_name_is_pub = true
         }
@@ -241,7 +291,7 @@ let app = async (req, res, protocol) => {
   let page = dir_name + '/' + file_name, data
   if (dir_name_is_pub) {
     try {
-      let data = await readFileAsync(site_root + page)
+      let data = await fs_readFile(site_root + page)
       console.log(
         site,
         'serving',
@@ -261,7 +311,7 @@ let app = async (req, res, protocol) => {
   else {
     temp = page + '.pub'
     try {
-      let data = await readFileAsync(site_root + temp)
+      let data = await fs_readFile(site_root + temp)
       console.log(
         site,
         'serving',
@@ -360,6 +410,22 @@ let app = async (req, res, protocol) => {
     }
   }
 
+  let favicons = await req_zip(site_root + '/favicons.zip')
+  temp = page.substring(1) // fix this to avoid leading / on all absolute paths
+  if (favicons.hasOwnProperty(temp)) {
+    let data = favicons[temp]
+    console.log(
+      site,
+      'serving',
+      page,
+      'length',
+      data.length,
+      'from favicons'
+    )
+    serve(res, 200, mime_type, data)
+    return
+  }
+
   console.log(site, 'file not found', page)
   return die(res)
 }
index 46fc271..c59f332 100644 (file)
@@ -13,7 +13,9 @@
     "jstemplate": "file:../jstemplate.git/jstemplate-3.4.9.tgz",
     "less": "^3.8.1",
     "querystring": "^0.2.0",
+    "stream-buffers": "^3.0.2",
     "url": "^0.11.0",
+    "yauzl": "^2.10.0",
     "zetjs": "file:../zettair.git/src/zetjs/zetjs-1.0.0.tgz"
   },
   "devDependencies": {},