Merge _config/server.json and _config/sites.jst into a single _config/server.jst...
authorNick Downing <nick@ndcode.org>
Sun, 18 Nov 2018 01:34:47 +0000 (12:34 +1100)
committerNick Downing <nick@ndcode.org>
Sun, 18 Nov 2018 01:42:00 +0000 (12:42 +1100)
.gitignore
Server.js
SiteDefault.js
SiteRoot.js
_config/server.jst [moved from _config/server.json with 67% similarity]
_config/sites.jst [deleted file]

index 574daf9..2520d42 100644 (file)
@@ -1,4 +1,5 @@
-.*.js
+.*.jst
+.*.min
 /jst_server-*.tgz
 /node_modules
 /yarn.lock
index ca7616b..80ec9db 100644 (file)
--- a/Server.js
+++ b/Server.js
@@ -68,9 +68,10 @@ let Server = function() {
   if (!this instanceof Server)
     throw Error('Server is a constructor')
 
-  this.mime_types = {}
-  this.listen = []
   this.enable_caching = false
+  this.listen = []
+  this.mime_types = {}
+  this.sites = {}
 
   this.build_cache_email = new BuildCache()
   this.build_cache_json = new BuildCache()
@@ -84,8 +85,7 @@ let Server = function() {
   this.build_cache_zip = new BuildCache()
   this.json_cache = new JSONCache(true)
 
-  this.mime_types = undefined
-  this.mime_type_html = undefined
+  this.mime_type_html = 'text/html; charset=utf-8'
   this.mime_type_default = 'application/octet-stream'
 }
 
@@ -505,116 +505,123 @@ Server.prototype.attach = function(server, protocol) {
 }
 
 Server.prototype.refresh_config = async function() {
-  let config = await this.get_json('_config/server.json')
-
-  this.enable_caching = config.enable_caching
+  try {
+    let config = await this.get_jst('_config/server.jst', '.')
 
-  this.mime_types = config.mime_types
-  this.mime_type_html =
-    Object.prototype.hasOwnProperty.call(this.mime_types, '.html') ?
-    this.mime_types['.html'] :
-    this.mime_type_default
+    this.enable_caching = config.enable_caching
 
-  let listen = []
-  for (let i = 0; i < config.listen.length; ++i)
-    listen.push(
-      Object.assign(
-        {
-          port: 0,
-          host: '0.0.0.0',
-          protocol: 'http:',
-          ssl_cert: '_ssl/localhost_cert_bundle.pem',
-          ssl_key: '_ssl/localhost_key.pem',
-        },
-        config.listen[i]
-      )
-    )
-  listen.sort(compare_listen)
-  //console.log('listen', listen)
-
-  // stop all servers no longer in configuration file
-  let i = 0
-  let j = 0
-  while (i < this.listen.length)
-    switch (
-      j < this.listen.length ?
-        compare_listen(this.listen[i], listen[j]) :
-        -1
-    ) {
-    case -1:
-      if (this.listen[i].server !== undefined) {
-        console.log(
-          `stop listening on ${this.listen[i].protocol}//${this.listen[i].host}:${this.listen[i].port}`
-        )
-        await new Promise(
-          (resolve, reject) => {
-            this.listen[i].server.close(
-              err => {
-                if (err)
-                  reject(err)
-                resolve()
-              }
-            )
-          }
+    let listen = []
+    for (let i = 0; i < config.listen.length; ++i)
+      listen.push(
+        Object.assign(
+          {
+            port: 0,
+            host: '0.0.0.0',
+            protocol: 'http:',
+            ssl_cert: '_ssl/localhost_cert_bundle.pem',
+            ssl_key: '_ssl/localhost_key.pem',
+          },
+          config.listen[i]
         )
-      }
-      ++i
-      break
-    case 0:
-      listen[j++].server = this.listen[i++].server
-      break
-    case 1:
-      listen[j++].server = undefined // just to be on the safe side
-      break
-    }
-
-  // then start all newly mentioned servers (or those which need retrying)
-  for (i = 0; i < listen.length; ++i)
-    if (listen[i].server === undefined) {
-      console.log(
-        `start listening on ${listen[i].protocol}//${listen[i].host}:${listen[i].port}`
       )
-      let server
-      switch (listen[i].protocol) {
-      case 'http:':
-        server = require('http').createServer()
+    listen.sort(compare_listen)
+    //console.log('listen', listen)
+
+    // stop all servers no longer in configuration file
+    let i = 0
+    let j = 0
+    while (i < this.listen.length)
+      switch (
+        j < this.listen.length ?
+          compare_listen(this.listen[i], listen[j]) :
+          -1
+      ) {
+      case -1:
+        if (this.listen[i].server !== undefined) {
+          console.log(
+            `stop listening on ${this.listen[i].protocol}//${this.listen[i].host}:${this.listen[i].port}`
+          )
+          await new Promise(
+            (resolve, reject) => {
+              this.listen[i].server.close(
+                err => {
+                  if (err)
+                    reject(err)
+                  resolve()
+                }
+              )
+            }
+          )
+        }
+        ++i
         break
-      case 'https:':
-        server = require('https').createServer(
-          {
-            'cert': await fs_readFile(listen[i].ssl_cert),
-            'key': await fs_readFile(listen[i].ssl_key)
-          }
-        )
+      case 0:
+        listen[j++].server = this.listen[i++].server
+        break
+      case 1:
+        listen[j++].server = undefined // just to be on the safe side
         break
-      default:
-        assert(false)
-      }
-      try {
-        await new Promise(
-          (resolve, reject) => {
-            server.on('listening', () => {resolve()})
-            server.on('error', err => {reject(err)})
-            server.listen(listen[i].port)
-            // should remove the listeners afterwards
-          }
-        )
       }
-      catch (err) {
-        if (err.code !== 'EADDRINUSE') // err type ??
-          throw err
+
+    // then start all newly mentioned servers (or those which need retrying)
+    for (i = 0; i < listen.length; ++i)
+      if (listen[i].server === undefined) {
         console.log(
-          `address ${listen[i].protocol}//${listen[i].host}:${listen[i].port} in use`
+          `start listening on ${listen[i].protocol}//${listen[i].host}:${listen[i].port}`
         )
-        continue // leaves listen[i].server undefined, will retry
+        let server
+        switch (listen[i].protocol) {
+        case 'http:':
+          server = require('http').createServer()
+          break
+        case 'https:':
+          server = require('https').createServer(
+            {
+              'cert': await fs_readFile(listen[i].ssl_cert),
+              'key': await fs_readFile(listen[i].ssl_key)
+            }
+          )
+          break
+        default:
+          assert(false)
+        }
+        try {
+          await new Promise(
+            (resolve, reject) => {
+              server.on('listening', () => {resolve()})
+              server.on('error', err => {reject(err)})
+              server.listen(listen[i].port)
+              // should remove the listeners afterwards
+            }
+          )
+        }
+        catch (err) {
+          if (err.code !== 'EADDRINUSE') // err type ??
+            throw err
+          console.log(
+            `address ${listen[i].protocol}//${listen[i].host}:${listen[i].port} in use`
+          )
+          continue // leaves listen[i].server undefined, will retry
+        }
+        this.attach(server, listen[i].protocol)
+        if (this.socket_io !== undefined)
+          this.socket_io.attach(server)
+        listen[i].server = server
       }
-      this.attach(server, listen[i].protocol)
-      if (this.socket_io !== undefined)
-        this.socket_io.attach(server)
-      listen[i].server = server
-    }
 
-  this.listen = listen
+    this.listen = listen
+
+    this.mime_types = config.mime_types
+    this.mime_type_html =
+      Object.prototype.hasOwnProperty.call(this.mime_types, '.html') ?
+      this.mime_types['.html'] :
+      this.mime_type_default
+
+    this.sites = config.sites
+  }
+  catch (err) {
+    console.log(`configuration error: ${err.stack || err.message}`)
+  }
 }
 
 Server.prototype.serve = function(response, status, mime_type, data, message) {
@@ -623,7 +630,7 @@ Server.prototype.serve = function(response, status, mime_type, data, message) {
   // html files will be direct recipient of links/bookmarks so can't have
   // a long lifetime, other files like css or images are often large files
   // and won't change frequently (but we'll need cache busting eventually)
-  if (this.caching && mime_type !== this.mime_types_html)
+  if (this.enable_caching && mime_type !== this.mime_type_html)
     response.setHeader('Cache-Control', 'max-age=3600')
   response.setHeader('Content-Type', mime_type)
   response.setHeader('Content-Length', data.length)
@@ -679,7 +686,6 @@ Server.prototype.redirect = function(response, location, message) {
 let site_factory_default = async (server, root) => new Site(server, root)
 
 Server.prototype.respond = async function(request, response, protocol) {
-  let sites = await this.get_jst('_config/sites.jst', '.')
   try {
     let parsed_url = url.parse(
       protocol + '//' + (request.headers.host || 'localhost') + request.url,
@@ -688,7 +694,7 @@ Server.prototype.respond = async function(request, response, protocol) {
     //console.log('parsed_url', parsed_url)
 
     if (
-      !Object.prototype.hasOwnProperty.call(sites, parsed_url.hostname)
+      !Object.prototype.hasOwnProperty.call(this.sites, parsed_url.hostname)
     ) {
       this.die(
         response,
@@ -708,7 +714,7 @@ Server.prototype.respond = async function(request, response, protocol) {
         mime_type = this.mime_types[extension]
     }
 
-    let site = sites[parsed_url.hostname]
+    let site = this.sites[parsed_url.hostname]
     await site.respond(
       {
         mime_type: mime_type,
index 8700188..6539b35 100644 (file)
@@ -1,10 +1,9 @@
 let SiteRoot = require('./SiteRoot')
 
-let SiteDefault = function(server, root, config) {
+let SiteDefault = function(server, root) {
   if (!this instanceof SiteDefault)
     throw Error('SiteDefault is a constructor')
   SiteRoot.call(this, server, root)
-  this.config = config
 }
 
 SiteDefault.prototype = Object.create(SiteRoot.prototype)
@@ -12,7 +11,7 @@ SiteDefault.prototype = Object.create(SiteRoot.prototype)
 SiteDefault.prototype.respond = async function(env) {
   let site
   try {
-    site = await this.get_jst(this.config)
+    site = await this.get_jst('/_config/site.jst')
   }
   catch (err) {
     if (!(err instanceof Error) || err.code !== 'ENOENT')
index 893f69a..0864575 100644 (file)
@@ -227,7 +227,7 @@ SiteRoot.prototype.serve_path = async function(env, pathname, components) {
       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
   }
 
similarity index 67%
rename from _config/server.json
rename to _config/server.jst
index c0fffbb..0705084 100644 (file)
@@ -1,4 +1,7 @@
-{
+let SiteDefault = require('../SiteDefault')
+let SiteRedirect = require('../SiteRedirect')
+
+return {
   "enable_caching": false,
   "listen": [
     {"port": 8080},
@@ -15,5 +18,9 @@
     ".png": "image/png",
     ".svg": "image/svg+xml",
     ".xml": "text/xml; charset=utf-8"
+  },
+  sites: {
+    'localhost': new SiteDefault(_server, 'site'),
+    'localhost.localdomain': new SiteRedirect(_server, 'localhost')
   }
 }
diff --git a/_config/sites.jst b/_config/sites.jst
deleted file mode 100644 (file)
index 92fbe1e..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-let SiteDefault = require('../SiteDefault')
-let SiteRedirect = require('../SiteRedirect')
-
-return {
-  'localhost': new SiteDefault(_server, 'site', '/_config/site.jst'),
-  'localhost.localdomain': new SiteRedirect(_server, 'localhost')
-}