You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

128 lines
3.6 KiB

9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
  1. #!/usr/bin/env node
  2. 'use strict'
  3. const ansi = require('ansi-escape-sequences')
  4. const path = require('path')
  5. const arrayify = require('array-back')
  6. const t = require('typical')
  7. const CommandLineTool = require('command-line-tool')
  8. const MiddlewareStack = require('./middleware-stack')
  9. const debug = require('./debug')
  10. const tool = new CommandLineTool()
  11. class LocalWebServer extends MiddlewareStack {
  12. _init (options) {
  13. this.options = this.options || Object.assign(options || {}, collectUserOptions(this.getOptionDefinitions()))
  14. }
  15. getApplication (options) {
  16. this._init(options)
  17. const Koa = require('koa')
  18. const app = new Koa()
  19. app.use(this.compose(this.options))
  20. return app
  21. }
  22. getServer (options) {
  23. const app = this.getApplication(options)
  24. options = this.options
  25. let key = options.key
  26. let cert = options.cert
  27. app.on('error', err => {
  28. if (options['log-format']) {
  29. console.error(ansi.format(err.message, 'red'))
  30. }
  31. })
  32. if (options.https) {
  33. key = path.resolve(__dirname, '..', 'ssl', '127.0.0.1.key')
  34. cert = path.resolve(__dirname, '..', 'ssl', '127.0.0.1.crt')
  35. }
  36. let server = null
  37. if (key && cert) {
  38. const fs = require('fs')
  39. const serverOptions = {
  40. key: fs.readFileSync(key),
  41. cert: fs.readFileSync(cert)
  42. }
  43. const https = require('https')
  44. server = https.createServer(serverOptions, app.callback())
  45. server.isHttps = true
  46. } else {
  47. const http = require('http')
  48. server = http.createServer(app.callback())
  49. }
  50. return server
  51. }
  52. listen (options, callback) {
  53. this._init(options)
  54. options = this.options
  55. if (options.verbose) {
  56. debug.setLevel(1)
  57. }
  58. if (options.config) {
  59. tool.stop(JSON.stringify(options, null, ' '), 0)
  60. } else if (options.version) {
  61. const pkg = require(path.resolve(__dirname, '..', 'package.json'))
  62. tool.stop(pkg.version)
  63. } else {
  64. const server = this.getServer()
  65. const port = options.port || 8000
  66. server.listen(port, () => {
  67. onServerUp(port, options.directory, server.isHttps)
  68. if (callback) callback()
  69. })
  70. return server
  71. }
  72. }
  73. }
  74. function onServerUp (port, directory, isHttps) {
  75. const ipList = getIPList(isHttps)
  76. .map(iface => `[underline]{${isHttps ? 'https' : 'http'}://${iface.address}:${port}}`)
  77. .join(', ')
  78. console.error(ansi.format(
  79. path.resolve(directory || '') === process.cwd()
  80. ? `serving at ${ipList}`
  81. : `serving [underline]{${directory}} at ${ipList}`
  82. ))
  83. }
  84. function getIPList (isHttps) {
  85. const flatten = require('reduce-flatten')
  86. const os = require('os')
  87. let ipList = Object.keys(os.networkInterfaces())
  88. .map(key => os.networkInterfaces()[key])
  89. .reduce(flatten, [])
  90. .filter(iface => iface.family === 'IPv4')
  91. ipList.unshift({ address: os.hostname() })
  92. return ipList
  93. }
  94. /**
  95. * Return default, stored and command-line options combined
  96. */
  97. function collectUserOptions (mwOptionDefinitions) {
  98. const loadConfig = require('config-master')
  99. const stored = loadConfig('local-web-server')
  100. const cli = require('../lib/cli-data')
  101. /* parse command line args */
  102. const definitions = cli.optionDefinitions.concat(arrayify(mwOptionDefinitions))
  103. let cliOptions = tool.getOptions(definitions, cli.usage(definitions))
  104. /* override stored config with command line options */
  105. const options = Object.assign(stored, cliOptions.server, cliOptions.middleware, cliOptions.misc)
  106. // console.error(require('util').inspect(options, { depth: 3, colors: true }))
  107. return options
  108. }
  109. module.exports = LocalWebServer