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.

108 lines
2.8 KiB

7 years ago
  1. /*
  2. * core.js: Core functionality for the Flatiron HTTP (with SPDY support) plugin.
  3. *
  4. * (C) 2011, Charlie Robbins & the Contributors
  5. * MIT LICENSE
  6. *
  7. */
  8. var http = require('http'),
  9. https = require('https'),
  10. fs = require('fs'),
  11. stream = require('stream'),
  12. HttpStream = require('./http-stream'),
  13. RoutingStream = require('./routing-stream');
  14. var core = exports;
  15. core.createServer = function (options) {
  16. var isArray = Array.isArray(options.after),
  17. credentials;
  18. if (!options) {
  19. throw new Error('options is required to create a server');
  20. }
  21. function requestHandler(req, res) {
  22. var routingStream = new RoutingStream({
  23. before: options.before,
  24. buffer: options.buffer,
  25. //
  26. // Remark: without new after is a huge memory leak that
  27. // pipes to every single open connection
  28. //
  29. after: isArray && options.after.map(function (After) {
  30. return new After;
  31. }),
  32. request: req,
  33. response: res,
  34. limit: options.limit,
  35. headers: options.headers
  36. });
  37. routingStream.on('error', function (err) {
  38. var fn = options.onError || core.errorHandler;
  39. fn(err, routingStream, routingStream.target, function () {
  40. routingStream.target.emit('next');
  41. });
  42. });
  43. req.pipe(routingStream);
  44. }
  45. //
  46. // both https and spdy requires same params
  47. //
  48. if (options.https || options.spdy) {
  49. if (options.https && options.spdy) {
  50. throw new Error('You shouldn\'t be using https and spdy simultaneously.');
  51. }
  52. var serverOptions,
  53. credentials,
  54. key = !options.spdy
  55. ? 'https'
  56. : 'spdy';
  57. serverOptions = options[key];
  58. if (!serverOptions.key || !serverOptions.cert) {
  59. throw new Error('Both options.' + key + '.`key` and options.' + key + '.`cert` are required.');
  60. }
  61. credentials = {
  62. key: fs.readFileSync(serverOptions.key),
  63. cert: fs.readFileSync(serverOptions.cert)
  64. };
  65. if (serverOptions.ca) {
  66. serverOptions.ca = !Array.isArray(serverOptions.ca)
  67. ? [serverOptions.ca]
  68. : serverOptions.ca
  69. credentials.ca = serverOptions.ca.map(function (ca) {
  70. return fs.readFileSync(ca);
  71. });
  72. }
  73. if (options.spdy) {
  74. // spdy is optional so we require module here rather than on top
  75. var spdy = require('spdy');
  76. return spdy.createServer(credentials, requestHandler);
  77. }
  78. return https.createServer(credentials, requestHandler);
  79. }
  80. return http.createServer(requestHandler);
  81. };
  82. core.errorHandler = function error(err, req, res) {
  83. if (err) {
  84. (this.res || res).writeHead(err.status || 500, err.headers || { "Content-Type": "text/plain" });
  85. (this.res || res).end(err.message + "\n");
  86. return;
  87. }
  88. (this.res || res).writeHead(404, {"Content-Type": "text/plain"});
  89. (this.res || res).end("Not Found\n");
  90. };