Make _config/server.jst construct the Server object and pass options into it, rather...
authorNick Downing <nick@ndcode.org>
Tue, 4 Dec 2018 02:42:48 +0000 (13:42 +1100)
committerNick Downing <nick@ndcode.org>
Tue, 4 Dec 2018 02:42:48 +0000 (13:42 +1100)
Server.js
_config/server.jst
cli.js

index 6ec6f1c..6cd296f 100644 (file)
--- a/Server.js
+++ b/Server.js
@@ -9,7 +9,7 @@ let util = require('util')
 
 let fs_readFile = util.promisify(fs.readFile)
 
-let Server = function(resources, options) {
+let Server = function(resources, options, prev_server) {
   if (!this instanceof Server)
     throw new Error('Server is a constructor')
   this.resources = resources
@@ -43,6 +43,8 @@ let Server = function(resources, options) {
     () => new JSTCache('.', {_jst_server: jst_server}, true)
   )
   this.roots = {}
+
+  this.listen = prev_server === undefined ? [] : prev_server.listen
 }
 
 let compare_listen = (a, b) => {
@@ -79,121 +81,106 @@ Server.prototype.attach = function(server, protocol) {
 }
 
 Server.prototype.refresh_config = async function() {
-  let config
-  try {
-    config = await this.jst_cache.get('_config/server.jst', true)
-  }
-  catch (err) {
-    console.log(`configuration error: ${err.stack || err.message}`)
-  }
-
-  if (config !== undefined) {
-    config = await config(this)
-    this.options.caching = config.enable_caching
+  let listen = []
+  for (let i = 0; i < this.options.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',
+        },
+        this.options.listen[i]
+      )
+    )
+  listen.sort(compare_listen)
+  //console.log('listen', listen)
 
-    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]
+  // 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}`
         )
-      )
-    listen.sort(compare_listen)
-    //console.log('listen', listen)
+        await new Promise(
+          (resolve, reject) => {
+            this.listen[i].server.close(
+              err => {
+                if (err)
+                  reject(err)
+                resolve()
+              }
+            )
+          }
+        )
+      }
+      ++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
+    }
 
-    // stop all servers no longer in configuration file
-    let i = 0
-    let j = 0
-    while (i < this.options.listen.length)
-      switch (
-        j < this.options.listen.length ?
-          compare_listen(this.options.listen[i], listen[j]) :
-          -1
-      ) {
-      case -1:
-        if (this.options.listen[i].server !== undefined) {
-          console.log(
-            `stop listening on ${this.options.listen[i].protocol}//${this.options.listen[i].host}:${this.options.listen[i].port}`
-          )
-          await new Promise(
-            (resolve, reject) => {
-              this.options.listen[i].server.close(
-                err => {
-                  if (err)
-                    reject(err)
-                  resolve()
-                }
-              )
-            }
-          )
-        }
-        ++i
-        break
-      case 0:
-        listen[j++].server = this.options.listen[i++].server
+  // 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()
         break
-      case 1:
-        listen[j++].server = undefined // just to be on the safe side
+      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)
       }
-
-    // then start all newly mentioned servers (or those which need retrying)
-    for (i = 0; i < listen.length; ++i)
-      if (listen[i].server === undefined) {
+      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(
-          `start listening on ${listen[i].protocol}//${listen[i].host}:${listen[i].port}`
+          `address ${listen[i].protocol}//${listen[i].host}:${listen[i].port} in use`
         )
-        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
+        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.options.listen = listen
-
-    this.options.hosts = config.hosts
-  }
+  this.listen = listen
 }
 
 Server.prototype.serve_internal = function(response, status, mime_type, data) {
index 1a67aae..cadf50d 100644 (file)
@@ -1,36 +1,5 @@
-return async server => (
-  {
-    "enable_caching": false,
-    "listen": [
-      {
-        "port": 8080
-      },
-      {
-        "port": 8443,
-        "protocol": "https:"
-      }
-    ],
-    "mime_types": {
-      ".css": "text/css; charset=utf-8",
-      ".html": "text/html; charset=utf-8",
-      ".ico": "image/x-icon",
-      ".jpg": "image/jpeg",
-      ".jpeg": "image/jpeg",
-      ".js": "application/javascript; charset=utf-8",
-      ".json": "application/json; charset=utf-8",
-      ".png": "image/png",
-      ".svg": "image/svg+xml",
-      ".xml": "text/xml; charset=utf-8"
-    },
-    hosts: {
-      "localhost": {
-        "type": "site",
-        "root": "site"
-      },
-      "localhost.localdomain": {
-        "type": "redirect",
-        "host": "localhost"
-      }
-    }
-  }
+return async (resources, prev_server) => new _jst_server.Server(
+  resources,
+  {},
+  prev_server
 )
diff --git a/cli.js b/cli.js
index 907b795..52d3892 100755 (executable)
--- a/cli.js
+++ b/cli.js
@@ -1,17 +1,30 @@
 #!/usr/bin/env node
 
 // must load index first, to avoid circular dependency issue
-let index = require('./index')
+let jst_server = require('./index')
+
+let JSTCache = require('@ndcode/jst_cache')
 let Resources = require('./Resources')
 let Server = require('./Server')
 
-let server = new Server(new Resources())
+let resources = new Resources()
+let jst_cache = resources.ref(
+  'jst_cache:.',
+  () => new JSTCache('.', {_jst_server: jst_server}, true)
+)
+let server = undefined
 
 // refresh the config immediately, then every 5 seconds,
 // use setTimeout() instead of setInterval() to avoid bunches
 // of calls after the computer has been suspended for a while
-let refresh_config = () => {
-  server.refresh_config()
+let refresh_config = async () => {
+  let prev_listen = server === undefined ? [] : server.listen
+  let config = await jst_cache.get('_config/server.jst', true)
+  if (config !== undefined) {
+    server = await config(resources, server)
+  }
+  server.refresh_config(prev_listen)
   setTimeout(refresh_config, 5000)
+  // returned Promise will be ignored
 }
 refresh_config()