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.

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