index.js 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. var Stream = require('stream');
  2. var EventEmitter = require('events').EventEmitter;
  3. module.exports = function (src) {
  4. var dst = null;
  5. var stream = copyStream(src);
  6. var pipe = stream.pipe;
  7. stream.pipe = function (target) {
  8. if (target && target.writeHead && target.setHeader) {
  9. dst = target;
  10. if (target.statusCode === 200) {
  11. target.statusCode = stream.statusCode;
  12. }
  13. stream.__defineGetter__('statusCode', function (code) {
  14. return target.statusCode;
  15. });
  16. stream.__defineSetter__('statusCode', function (code) {
  17. target.statusCode = code;
  18. });
  19. proxied.forEach(function (p) {
  20. target[p.name].apply(target, p.arguments);
  21. });
  22. stream.emit('response', target);
  23. }
  24. return pipe.apply(this, arguments);
  25. };
  26. stream.statusCode = 200;
  27. var proxied = [];
  28. var methods = [
  29. 'writeContinue', 'writeHead', 'setHeader', 'sendDate', 'getHeader',
  30. 'removeHeader', 'addTrailers'
  31. ];
  32. methods.forEach(function (name) {
  33. stream[name] = function () {
  34. var prevented = false;
  35. var prevent = function () { prevented = true };
  36. stream.emit(name, arguments, prevent);
  37. if (prevented) return;
  38. if (dst) return dst[name].apply(dst, arguments);
  39. // return codes can't work yet here because we don't have the
  40. // response, but that should only matter for getHeader()
  41. proxied.push({ name : name, arguments : arguments });
  42. };
  43. });
  44. return stream;
  45. };
  46. function copyStream (src) {
  47. var s = new Stream;
  48. s.writable = true;
  49. s.readable = true;
  50. [ 'write', 'end', 'destroy', 'pause', 'resume' ]
  51. .forEach(function (name) {
  52. if (src[name]) s[name] = src[name].bind(src);
  53. })
  54. ;
  55. [ 'data', 'end', 'error', 'close', 'drain', 'pipe' ]
  56. .forEach(function (name) {
  57. src.on(name, s.emit.bind(s, name));
  58. })
  59. ;
  60. return s;
  61. }