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.

131 lines
3.4 KiB

12 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. #!/usr/bin/env node
  2. 'use strict'
  3. const localWebServer = require('../')
  4. const cliOptions = require('../lib/cli-options')
  5. const commandLineArgs = require('command-line-args')
  6. const ansi = require('ansi-escape-sequences')
  7. const loadConfig = require('config-master')
  8. const path = require('path')
  9. const s = require('string-tools')
  10. const os = require('os')
  11. const arrayify = require('array-back')
  12. const t = require('typical')
  13. const cli = commandLineArgs(cliOptions.definitions)
  14. const usage = cli.getUsage(cliOptions.usageData)
  15. const stored = loadConfig('local-web-server')
  16. const options = collectOptions()
  17. if (options.misc.help) stop(usage, 0)
  18. if (options.misc.config) stop(JSON.stringify(options.server, null, ' '), 0)
  19. validateOptions(options)
  20. const app = localWebServer({
  21. static: {
  22. root: options.server.directory,
  23. options: {
  24. hidden: true
  25. }
  26. },
  27. serveIndex: {
  28. path: options.server.directory,
  29. options: {
  30. icons: true,
  31. hidden: true
  32. }
  33. },
  34. log: {
  35. format: options.server['log-format']
  36. },
  37. compress: options.server.compress,
  38. mime: options.server.mime,
  39. forbid: options.server.forbid,
  40. spa: options.server.spa,
  41. 'no-cache': options.server['no-cache'],
  42. rewrite: options.server.rewrite,
  43. verbose: options.server.verbose,
  44. mocks: options.server.mocks
  45. })
  46. let isHttps = false
  47. if (options.server.key && options.server.cert) {
  48. const https = require('https')
  49. const fs = require('fs')
  50. isHttps = true
  51. const serverOptions = {
  52. key: fs.readFileSync(options.server.key),
  53. cert: fs.readFileSync(options.server.cert)
  54. }
  55. const server = https.createServer(serverOptions, app.callback())
  56. server.listen(options.server.port, onServerUp)
  57. } else {
  58. app.listen(options.server.port, onServerUp)
  59. }
  60. function stop (msgs, exitCode) {
  61. arrayify(msgs).forEach(msg => console.error(ansi.format(msg)))
  62. process.exit(exitCode)
  63. }
  64. function onServerUp () {
  65. const ipList = Object.keys(os.networkInterfaces())
  66. .map(key => os.networkInterfaces()[key])
  67. .reduce((prev, curr) => prev = prev.concat(curr), [])
  68. .filter(iface => iface.family === 'IPv4')
  69. .map(iface => `[underline]{${isHttps ? 'https' : 'http'}://${iface.address}:${options.server.port}}`)
  70. .join(', ')
  71. console.error(ansi.format(
  72. path.resolve(options.server.directory) === process.cwd()
  73. ? `serving at ${ipList}`
  74. : `serving [underline]{${options.server.directory}} at ${ipList}`
  75. ))
  76. }
  77. function collectOptions () {
  78. let options = {}
  79. /* parse command line args */
  80. try {
  81. options = cli.parse()
  82. } catch (err) {
  83. stop([ `[red]{Error}: ${err.message}`, usage ], 1)
  84. }
  85. const builtIn = {
  86. port: 8000,
  87. directory: process.cwd(),
  88. forbid: [],
  89. rewrite: []
  90. }
  91. if (options.server.rewrite) {
  92. options.server.rewrite = parseRewriteRules(options.server.rewrite)
  93. }
  94. /* override built-in defaults with stored config and then command line args */
  95. options.server = Object.assign(builtIn, stored, options.server)
  96. return options
  97. }
  98. function parseRewriteRules (rules) {
  99. return rules && rules.map(rule => {
  100. const matches = rule.match(/(\S*)\s*->\s*(\S*)/)
  101. return {
  102. from: matches[1],
  103. to: matches[2]
  104. }
  105. })
  106. }
  107. function validateOptions (options) {
  108. function invalid (msg) {
  109. return `[red underline]{Invalid:} [bold]{${msg}}`
  110. }
  111. if (!t.isNumber(options.server.port)) {
  112. stop([ invalid(`--port must be numeric [value=${options.server.port}]`), usage ], 1)
  113. }
  114. }