New recursive directory resolution scheme, controlled by new functions serve_dir...
authorNick Downing <nick@ndcode.org>
Fri, 16 Nov 2018 14:18:35 +0000 (01:18 +1100)
committerNick Downing <nick@ndcode.org>
Fri, 16 Nov 2018 14:18:35 +0000 (01:18 +1100)
Server.js
SiteConfig.js [deleted file]
SiteRoot.js

index 682feb3..3cba05a 100644 (file)
--- a/Server.js
+++ b/Server.js
@@ -447,11 +447,11 @@ Server.prototype.respond = async function(request, response, protocol) {
     let mime_type = this.mime_type_default
     let i = parsed_url.pathname.lastIndexOf('.')
     if (i !== -1) {
-      let filetype = parsed_url.pathname.slice(i)
+      let extension = parsed_url.pathname.slice(i)
       if (
-        Object.prototype.hasOwnProperty.call(this.mime_types, filetype)
+        Object.prototype.hasOwnProperty.call(this.mime_types, extension)
       )
-        mime_type = this.mime_types[filetype]
+        mime_type = this.mime_types[extension]
     }
 
     let site = sites[parsed_url.hostname]
@@ -460,7 +460,6 @@ Server.prototype.respond = async function(request, response, protocol) {
         mime_type: mime_type,
         parsed_url: parsed_url,
         pathname: parsed_url.pathname,
-        pathname_pos: 0,
         response: response,
         request: request,
         site: site
diff --git a/SiteConfig.js b/SiteConfig.js
deleted file mode 100644 (file)
index eb272e6..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-let AbstractSite = require('AbstractSite')
-
-let Site = function(server, root, config_file) {
-  AbstractSite.call(this, server)
-  this.root = 
-  this.new_host = new_host
-}
-
-Site.prototype = Object.create(AbstractSite.prototype)
-
-SiteRedirect.respond = async function(env) {
-  let new_host = this.new_host
-  if (parsed_url.port !== undefined)
-    new_host += ':' + parsed_url.port
-  this.redirect(
-    response,
-    `${parsed_url.protocol}//${new_host}${request.url}`,
-    `redirecting ${parsed_url.host} to ${new_host}`
-  )
-}
index da62f1c..af058fe 100644 (file)
@@ -81,7 +81,7 @@ SiteRoot.prototype.serve_jst = async function(env, pathname) {
 }
 
 SiteRoot.prototype.serve_less = async function(env, pathname) {
-  if (env.pathname.slice(env.pathname_pos) !== '.css')
+  if (pathname.slice(-9) !== '.css.less')
     return false
  
   let data 
@@ -111,105 +111,115 @@ SiteRoot.prototype.serve_fs = async function(env, pathname) {
   return true
 }
 
-SiteRoot.prototype.serve_zip = async function(env, pathname) {
+SiteRoot.prototype.serve_zip = async function(env, zipname, pathname) {
   let zip 
   try {
-    zip = await this.server.get_zip(pathname)
+    zip = await this.server.get_zip(zipname)
   }
   catch (err) {
     if (!(err instanceof Error) || err.code !== 'ENOENT')
       throw err
     return false
   }
-  if (!Object.prototype.hasOwnProperty.call(zip, env.pathname))
+  if (!Object.prototype.hasOwnProperty.call(zip, pathname))
     return false
-  this.serve(env, 200, zip[env.pathname], 'zip')
+  this.serve(env, 200, zip[pathname], 'zip')
   return true
 }
 
-SiteRoot.prototype.respond = async function(env) {
-  while (true) {
-    if (env.pathname_pos >= env.pathname.length) {
-      // directory without trailing slash
-      this.redirect(env, env.pathname + '/index.html')
-      return
-    }
-
-    assert(env.pathname.charAt(env.pathname_pos) === '/')
-    let i = env.pathname_pos + 1
-    let j = env.pathname.indexOf('/', i)
-    if (j === -1)
-      j = env.pathname.length
-    let filename = env.pathname.slice(i, j)
-
-    if (filename.length === 0) {
-      if (j >= env.pathname.length)
-        // directory with trailing slash
-        this.redirect(env, env.pathname + 'index.html')
-      else
-        this.die(env, `empty directory name in ${env.pathname}`)
-      return
-    }
-
-    if (
-      filename.charAt(0) === '.' ||
-      filename.charAt(0) === '_'
-    ) {
-      this.die(env, `bad component "${filename}" in ${env.pathname}`)
-      return
-    }
-
-    let k = filename.lastIndexOf('.')
-    if (k === -1)
-      k = filename.length
-    let filetype = filename.slice(k)
-
-    if (
-      filetype.length !== 0 &&
-      Object.prototype.hasOwnProperty.call(this.server.mime_types, filetype)
-    ) {
-      if (j < env.pathname.length) {
-        this.die(env, `non-directory filetype "${filetype}" in ${env.pathname}`)
-        return
-      }
-      env.pathname_pos = i + k // advance to "." at start of filetype
-      break
-    }
-
-    env.pathname_pos = j
-    let pathname = env.pathname.slice(0, env.pathname_pos)
-    if (await this.serve_jst(env, this.root + pathname + '.dir.jst'))
-      return
-
-    let stats
-    try {
-      stats = await fs_stat(this.root + 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,
-        j < env.pathname.length ?
-          `not directory ${pathname}` :
-          `unknown filetype "${filetype}" in ${pathname}`
-      )
-      return
-    }
-  }    
-
+SiteRoot.prototype.serve_file = async function(env, pathname) {
+  //console.log(`serve_file ${pathname}`)
   if (
-    !await this.serve_jst(env, this.root + env.pathname + '.jst') &&
-    !await this.serve_less(env, this.root + env.pathname + '.less') &&
-    !await this.serve_fs(env, this.root + env.pathname) &&
-    !await this.serve_zip(env, this.root + '/_favicon/favicons.zip')
+    !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}`)
   }
 }
 
+SiteRoot.prototype.serve_dir = async function(env, dirname, pathname) {
+  //console.log(`serve_dir ${dirname} ${pathname}`)
+  if (pathname.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)
+      this.die(env, `empty directory name in ${env.pathname}`)
+    else
+      // directory with trailing slash
+      this.redirect(env, env.pathname + 'index.html')
+    return
+  }
+
+  if (
+    component.charAt(1) === '.' ||
+    component.charAt(1) === '_'
+  ) {
+    this.die(env, `bad component "${component}" in ${env.pathname}`)
+    return
+  }
+
+  let j = component.lastIndexOf('.')
+  if (j === -1)
+    j = component.length
+  let extension = component.slice(j)
+
+  if (
+    extension.length !== 0 &&
+    Object.prototype.hasOwnProperty.call(this.server.mime_types, extension)
+  ) {
+    if (i < pathname.length)
+      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
+  }
+  this.serve_dir(env, dirname, pathname.slice(i))
+}
+
+SiteRoot.prototype.respond = async function(env) {
+  if (
+    !await this.serve_zip(
+      env,
+      this.root + '/_favicon/favicons.zip',
+      env.pathname
+    )
+  )
+    this.serve_dir(env, this.root, env.pathname)
+}
+
 module.exports = SiteRoot