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
() => new JSTCache('.', {_jst_server: jst_server}, true)
)
this.roots = {}
+
+ this.listen = prev_server === undefined ? [] : prev_server.listen
}
let compare_listen = (a, b) => {
}
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) {
#!/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()