|
|
@ -1,97 +1,91 @@ |
|
|
|
#!/usr/bin/env node
|
|
|
|
'use strict' |
|
|
|
const localWebServer = require('../') |
|
|
|
const cliOptions = require('../lib/cli-options') |
|
|
|
const commandLineArgs = require('command-line-args') |
|
|
|
const cli = require('../lib/cli-data') |
|
|
|
const commandLineUsage = require('command-line-usage') |
|
|
|
const ansi = require('ansi-escape-sequences') |
|
|
|
const loadConfig = require('config-master') |
|
|
|
const path = require('path') |
|
|
|
const os = require('os') |
|
|
|
const arrayify = require('array-back') |
|
|
|
const t = require('typical') |
|
|
|
const flatten = require('reduce-flatten') |
|
|
|
|
|
|
|
const usage = commandLineUsage(cliOptions.usageData) |
|
|
|
function ws () { |
|
|
|
const usage = commandLineUsage(cli.usageData) |
|
|
|
|
|
|
|
let options |
|
|
|
let isHttps = false |
|
|
|
let options |
|
|
|
|
|
|
|
try { |
|
|
|
options = collectOptions() |
|
|
|
} catch (err) { |
|
|
|
stop([ `[red]{Error}: ${err.message}`, usage ], 1) |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
if (options.misc.help) { |
|
|
|
stop(usage, 0) |
|
|
|
} else if (options.misc.config) { |
|
|
|
stop(JSON.stringify(options.server, null, ' '), 0) |
|
|
|
} else { |
|
|
|
const valid = validateOptions(options) |
|
|
|
if (!valid) { |
|
|
|
/* gracefully end the process */ |
|
|
|
try { |
|
|
|
options = collectOptions() |
|
|
|
} catch (err) { |
|
|
|
stop([ `[red]{Error}: ${err.message}`, usage ], 1) |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
const Koa = require('koa') |
|
|
|
const app = new Koa() |
|
|
|
if (options.misc.help) { |
|
|
|
stop(usage, 0) |
|
|
|
} else if (options.misc.config) { |
|
|
|
stop(JSON.stringify(options.server, null, ' '), 0) |
|
|
|
} else { |
|
|
|
const localWebServer = require('../') |
|
|
|
const Koa = require('koa') |
|
|
|
|
|
|
|
app.on('error', err => { |
|
|
|
if (options.server['log-format']) { |
|
|
|
console.error(ansi.format(err.message, 'red')) |
|
|
|
} |
|
|
|
}) |
|
|
|
const valid = validateOptions(options, usage) |
|
|
|
if (!valid) return |
|
|
|
|
|
|
|
const ws = localWebServer({ |
|
|
|
static: { |
|
|
|
root: options.server.directory, |
|
|
|
options: { |
|
|
|
hidden: true |
|
|
|
} |
|
|
|
}, |
|
|
|
serveIndex: { |
|
|
|
path: options.server.directory, |
|
|
|
options: { |
|
|
|
icons: true, |
|
|
|
hidden: true |
|
|
|
} |
|
|
|
}, |
|
|
|
log: { |
|
|
|
format: options.server['log-format'] |
|
|
|
}, |
|
|
|
compress: options.server.compress, |
|
|
|
mime: options.server.mime, |
|
|
|
forbid: options.server.forbid, |
|
|
|
spa: options.server.spa, |
|
|
|
'no-cache': options.server['no-cache'], |
|
|
|
rewrite: options.server.rewrite, |
|
|
|
verbose: options.server.verbose, |
|
|
|
mocks: options.server.mocks |
|
|
|
}) |
|
|
|
const app = new Koa() |
|
|
|
|
|
|
|
app.use(ws) |
|
|
|
app.on('error', err => { |
|
|
|
if (options.server['log-format']) { |
|
|
|
console.error(ansi.format(err.message, 'red')) |
|
|
|
} |
|
|
|
}) |
|
|
|
|
|
|
|
const ws = localWebServer({ |
|
|
|
static: { |
|
|
|
root: options.server.directory, |
|
|
|
options: { |
|
|
|
hidden: true |
|
|
|
} |
|
|
|
}, |
|
|
|
serveIndex: { |
|
|
|
path: options.server.directory, |
|
|
|
options: { |
|
|
|
icons: true, |
|
|
|
hidden: true |
|
|
|
} |
|
|
|
}, |
|
|
|
log: { |
|
|
|
format: options.server['log-format'] |
|
|
|
}, |
|
|
|
compress: options.server.compress, |
|
|
|
mime: options.server.mime, |
|
|
|
forbid: options.server.forbid, |
|
|
|
spa: options.server.spa, |
|
|
|
'no-cache': options.server['no-cache'], |
|
|
|
rewrite: options.server.rewrite, |
|
|
|
verbose: options.server.verbose, |
|
|
|
mocks: options.server.mocks |
|
|
|
}) |
|
|
|
|
|
|
|
app.use(ws) |
|
|
|
|
|
|
|
if (options.server.https) { |
|
|
|
options.server.key = path.resolve(__dirname, '..', 'ssl', '127.0.0.1.key') |
|
|
|
options.server.cert = path.resolve(__dirname, '..', 'ssl', '127.0.0.1.crt') |
|
|
|
} |
|
|
|
|
|
|
|
if (options.server.https) { |
|
|
|
options.server.key = path.resolve(__dirname, '..', 'ssl', '127.0.0.1.key') |
|
|
|
options.server.cert = path.resolve(__dirname, '..', 'ssl', '127.0.0.1.crt') |
|
|
|
} |
|
|
|
if (options.server.key && options.server.cert) { |
|
|
|
const https = require('https') |
|
|
|
const fs = require('fs') |
|
|
|
|
|
|
|
if (options.server.key && options.server.cert) { |
|
|
|
const https = require('https') |
|
|
|
const fs = require('fs') |
|
|
|
isHttps = true |
|
|
|
const serverOptions = { |
|
|
|
key: fs.readFileSync(options.server.key), |
|
|
|
cert: fs.readFileSync(options.server.cert) |
|
|
|
} |
|
|
|
|
|
|
|
const serverOptions = { |
|
|
|
key: fs.readFileSync(options.server.key), |
|
|
|
cert: fs.readFileSync(options.server.cert) |
|
|
|
const server = https.createServer(serverOptions, app.callback()) |
|
|
|
server.listen(options.server.port, onServerUp.bind(null, options, true)) |
|
|
|
} else { |
|
|
|
app.listen(options.server.port, onServerUp.bind(null, options)) |
|
|
|
} |
|
|
|
|
|
|
|
const server = https.createServer(serverOptions, app.callback()) |
|
|
|
server.listen(options.server.port, onServerUp) |
|
|
|
} else { |
|
|
|
app.listen(options.server.port, onServerUp) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -100,13 +94,8 @@ function stop (msgs, exitCode) { |
|
|
|
process.exitCode = exitCode |
|
|
|
} |
|
|
|
|
|
|
|
function onServerUp () { |
|
|
|
let ipList = Object.keys(os.networkInterfaces()) |
|
|
|
.map(key => os.networkInterfaces()[key]) |
|
|
|
.reduce(flatten, []) |
|
|
|
.filter(iface => iface.family === 'IPv4') |
|
|
|
ipList.unshift({ address: os.hostname() }) |
|
|
|
ipList = ipList |
|
|
|
function onServerUp (options, isHttps) { |
|
|
|
const ipList = getIPList(isHttps) |
|
|
|
.map(iface => `[underline]{${isHttps ? 'https' : 'http'}://${iface.address}:${options.server.port}}`) |
|
|
|
.join(', ') |
|
|
|
|
|
|
@ -117,12 +106,28 @@ function onServerUp () { |
|
|
|
)) |
|
|
|
} |
|
|
|
|
|
|
|
function getIPList (isHttps) { |
|
|
|
const flatten = require('reduce-flatten') |
|
|
|
const os = require('os') |
|
|
|
|
|
|
|
let ipList = Object.keys(os.networkInterfaces()) |
|
|
|
.map(key => os.networkInterfaces()[key]) |
|
|
|
.reduce(flatten, []) |
|
|
|
.filter(iface => iface.family === 'IPv4') |
|
|
|
ipList.unshift({ address: os.hostname() }) |
|
|
|
return ipList |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Return default, stored and command-line options combined |
|
|
|
*/ |
|
|
|
function collectOptions () { |
|
|
|
const commandLineArgs = require('command-line-args') |
|
|
|
const loadConfig = require('config-master') |
|
|
|
const stored = loadConfig('local-web-server') |
|
|
|
let options = {} |
|
|
|
|
|
|
|
/* parse command line args */ |
|
|
|
options = commandLineArgs(cliOptions.definitions) |
|
|
|
let options = commandLineArgs(cli.definitions) |
|
|
|
|
|
|
|
const builtIn = { |
|
|
|
port: 8000, |
|
|
@ -150,7 +155,7 @@ function parseRewriteRules (rules) { |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
function validateOptions (options) { |
|
|
|
function validateOptions (options, usage) { |
|
|
|
let valid = true |
|
|
|
function invalid (msg) { |
|
|
|
return `[red underline]{Invalid:} [bold]{${msg}}` |
|
|
@ -162,3 +167,5 @@ function validateOptions (options) { |
|
|
|
} |
|
|
|
return valid |
|
|
|
} |
|
|
|
|
|
|
|
ws() |
xxxxxxxxxx