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.

139 lines
3.3 KiB

7 years ago
  1. 'use strict';
  2. var fs = require('fs'),
  3. union = require('union'),
  4. ecstatic = require('ecstatic'),
  5. httpProxy = require('http-proxy'),
  6. corser = require('corser');
  7. //
  8. // Remark: backwards compatibility for previous
  9. // case convention of HTTP
  10. //
  11. exports.HttpServer = exports.HTTPServer = HttpServer;
  12. /**
  13. * Returns a new instance of HttpServer with the
  14. * specified `options`.
  15. */
  16. exports.createServer = function (options) {
  17. return new HttpServer(options);
  18. };
  19. /**
  20. * Constructor function for the HttpServer object
  21. * which is responsible for serving static files along
  22. * with other HTTP-related features.
  23. */
  24. function HttpServer(options) {
  25. options = options || {};
  26. if (options.root) {
  27. this.root = options.root;
  28. }
  29. else {
  30. try {
  31. fs.lstatSync('./public');
  32. this.root = './public';
  33. }
  34. catch (err) {
  35. this.root = './';
  36. }
  37. }
  38. this.headers = options.headers || {};
  39. this.cache = options.cache === undefined ? 3600 : options.cache; // in seconds.
  40. this.showDir = options.showDir !== 'false';
  41. this.autoIndex = options.autoIndex !== 'false';
  42. this.contentType = options.contentType || 'application/octet-stream';
  43. if (options.ext) {
  44. this.ext = options.ext === true
  45. ? 'html'
  46. : options.ext;
  47. }
  48. var before = options.before ? options.before.slice() : [];
  49. before.push(function (req, res) {
  50. if (options.logFn) {
  51. options.logFn(req, res);
  52. }
  53. res.emit('next');
  54. });
  55. if (options.cors) {
  56. this.headers['Access-Control-Allow-Origin'] = '*';
  57. this.headers['Access-Control-Allow-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept, Range';
  58. if (options.corsHeaders) {
  59. options.corsHeaders.split(/\s*,\s*/)
  60. .forEach(function (h) { this.headers['Access-Control-Allow-Headers'] += ', ' + h; }, this);
  61. }
  62. before.push(corser.create(options.corsHeaders ? {
  63. requestHeaders: this.headers['Access-Control-Allow-Headers'].split(/\s*,\s*/)
  64. } : null));
  65. }
  66. if (options.robots) {
  67. before.push(function (req, res) {
  68. if (req.url === '/robots.txt') {
  69. res.setHeader('Content-Type', 'text/plain');
  70. var robots = options.robots === true
  71. ? 'User-agent: *\nDisallow: /'
  72. : options.robots.replace(/\\n/, '\n');
  73. return res.end(robots);
  74. }
  75. res.emit('next');
  76. });
  77. }
  78. before.push(ecstatic({
  79. root: this.root,
  80. cache: this.cache,
  81. showDir: this.showDir,
  82. autoIndex: this.autoIndex,
  83. defaultExt: this.ext,
  84. contentType: this.contentType,
  85. handleError: typeof options.proxy !== 'string'
  86. }));
  87. if (typeof options.proxy === 'string') {
  88. var proxy = httpProxy.createProxyServer({});
  89. before.push(function (req, res) {
  90. proxy.web(req, res, {
  91. target: options.proxy,
  92. changeOrigin: true
  93. });
  94. });
  95. }
  96. var serverOptions = {
  97. before: before,
  98. headers: this.headers,
  99. onError: function (err, req, res) {
  100. if (options.logFn) {
  101. options.logFn(req, res, err);
  102. }
  103. res.end();
  104. }
  105. };
  106. if (options.https) {
  107. serverOptions.https = options.https;
  108. }
  109. this.server = union.createServer(serverOptions);
  110. }
  111. HttpServer.prototype.listen = function () {
  112. this.server.listen.apply(this.server, arguments);
  113. };
  114. HttpServer.prototype.close = function () {
  115. return this.server.close();
  116. };