Fix a number of async/await bugs, separate serve_dir() into serve_path() which does...
authorNick Downing <nick@ndcode.org>
Fri, 16 Nov 2018 23:44:16 +0000 (10:44 +1100)
committerNick Downing <nick@ndcode.org>
Fri, 16 Nov 2018 23:44:40 +0000 (10:44 +1100)
Server.js
SiteRoot.js

index 3cba05a..7b27ae3 100644 (file)
--- a/Server.js
+++ b/Server.js
@@ -172,9 +172,9 @@ Server.prototype.get_zip = function(pathname) {
         read_stream.pipe(write_stream)
         data = await data
 
-        let pathname = '/' + entries[i].fileName
-        console.log('entry pathname', pathname, 'size', data.length)
-        result.value[pathname] = data
+        let entry_pathname = '/' + entries[i].fileName
+        console.log('entry pathname', entry_pathname, 'size', data.length)
+        result.value[entry_pathname] = data
       }
       await zipfile.close()
     }
@@ -455,7 +455,7 @@ Server.prototype.respond = async function(request, response, protocol) {
     }
 
     let site = sites[parsed_url.hostname]
-    site.respond(
+    await site.respond(
       {
         mime_type: mime_type,
         parsed_url: parsed_url,
index af058fe..6e55c8a 100644 (file)
@@ -66,7 +66,7 @@ SiteRoot.prototype.modify_json =
     )
   }
 
-SiteRoot.prototype.serve_jst = async function(env, pathname) {
+SiteRoot.prototype.serve_jst = async function(env, pathname, ...args) {
   let template
   try {
     template = await this.server.get_jst(pathname, this.root)
@@ -76,7 +76,7 @@ SiteRoot.prototype.serve_jst = async function(env, pathname) {
       throw err
     return false
   }
-  await template(env)
+  await template(env, ...args)
   return true
 }
 
@@ -129,97 +129,100 @@ SiteRoot.prototype.serve_zip = async function(env, zipname, pathname) {
 
 SiteRoot.prototype.serve_file = async function(env, pathname) {
   //console.log(`serve_file ${pathname}`)
-  if (
-    !await this.serve_jst(env, pathname + '.jst') &&
-    !await this.serve_less(env, pathname + '.less') &&
-    !await this.serve_fs(env, pathname)
-  ) {
-    this.die(env, `file not found ${env.pathname}`)
+  if (await this.serve_jst(env, pathname + '.jst'))
+    return
+  if (await this.serve_less(env, pathname + '.less'))
+    return
+  if (await this.serve_fs(env, pathname))
+    return
+  this.die(env, `file not found ${env.pathname}`)
+}
+
+SiteRoot.prototype.serve_dir = async function(env, pathname, components) {
+  if (await this.serve_jst(env, pathname + '.dir.jst', components))
+    return
+
+  let stats
+  try {
+    stats = await fs_stat(pathname)
+  }
+  catch (err) {
+    if (!(err instanceof Error) || err.code !== 'ENOENT')
+      throw err
+    this.die(env, `directory not found ${pathname}`)
+    return
+  }
+  if (!stats.isDirectory()) {
+    this.die(
+      env,
+      components.length > 1 ?
+        `not directory ${pathname}` :
+        `unknown extension "${extension}" in ${env.pathname}`
+    )
+    return
   }
+  return /*await*/ this.serve_path(env, pathname, components)
 }
 
-SiteRoot.prototype.serve_dir = async function(env, dirname, pathname) {
-  //console.log(`serve_dir ${dirname} ${pathname}`)
-  if (pathname.length == 0) {
+SiteRoot.prototype.serve_path = async function(env, pathname, components) {
+  //console.log(`serve_path ${pathname} ${components}`)
+  if (components.length === 0) {
     // directory without trailing slash
     this.redirect(env, env.pathname + '/index.html')
     return
   }
 
-  assert(pathname.charAt(0) === '/')
-  let i = pathname.indexOf('/', 1)
-  if (i === -1)
-    i = pathname.length
-  let component = pathname.slice(0, i)
-
-  if (component.length === 1) {
-    if (i < pathname.length)
+  if (components[0].length === 0) {
+    if (components.length > 1)
       this.die(env, `empty directory name in ${env.pathname}`)
     else
       // directory with trailing slash
-      this.redirect(env, env.pathname + 'index.html')
+      this.redirect(env, env.pathname + '/index.html')
     return
   }
 
   if (
-    component.charAt(1) === '.' ||
-    component.charAt(1) === '_'
+    components[0].charAt(0) === '.' ||
+    components[0].charAt(0) === '_'
   ) {
-    this.die(env, `bad component "${component}" in ${env.pathname}`)
+    this.die(env, `bad component "${components[0]}" in ${env.pathname}`)
     return
   }
 
-  let j = component.lastIndexOf('.')
-  if (j === -1)
-    j = component.length
-  let extension = component.slice(j)
+  let i = components[0].lastIndexOf('.')
+  if (i === -1)
+    i = components[0].length
+  let extension = components[0].slice(i)
 
+  pathname = `${pathname}/${components[0]}`
   if (
     extension.length !== 0 &&
     Object.prototype.hasOwnProperty.call(this.server.mime_types, extension)
   ) {
-    if (i < pathname.length)
+    if (components.length > 1) {
       this.die(env, `non-directory extension "${extension}" in ${env.pathname}`)
-    else
-      this.serve_file(env, dirname + pathname)
-    return
-  }
-
-  dirname += component
-  if (await this.serve_jst(env, dirname + '.dir.jst'))
-    return
-
-  let stats
-  try {
-    stats = await fs_stat(dirname)
-  }
-  catch (err) {
-    if (!(err instanceof Error) || err.code !== 'ENOENT')
-      throw err
-    this.die(env, `directory not found ${dirname}`)
-    return
-  }
-  if (!stats.isDirectory()) {
-    this.die(
-      env,
-      i < pathname.length ?
-        `not directory ${dirname}` :
-        `unknown extension "${extension}" in ${env.pathname}`
-    )
-    return
+      return
+    }
+    return /*await*/ this.serve_file(env, pathname)
   }
-  this.serve_dir(env, dirname, pathname.slice(i))
+  return /*await*/ this.serve_dir(env, pathname, components.slice(1))
 }
 
 SiteRoot.prototype.respond = async function(env) {
   if (
-    !await this.serve_zip(
+    await this.serve_zip(
       env,
       this.root + '/_favicon/favicons.zip',
       env.pathname
     )
   )
-    this.serve_dir(env, this.root, env.pathname)
+    return
+  let components = env.pathname.split('/')
+  if (components.length) {
+    assert(components[0].length == 0)
+    components = components.slice(1)
+  }
+  return /*await*/ this.serve_path(env, this.root, components)
 }
 
 module.exports = SiteRoot