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.

250 lines
6.6 KiB

4 years ago
  1. var assert = require('assert');
  2. var util = require('util');
  3. var Buffer = require('buffer').Buffer;
  4. // Node.js version
  5. var mode = /^v0\.8\./.test(process.version) ? 'rusty' :
  6. /^v0\.(9|10)\./.test(process.version) ? 'old' :
  7. /^v0\.12\./.test(process.version) ? 'normal' :
  8. 'modern';
  9. var HTTPParser;
  10. var methods;
  11. var reverseMethods;
  12. var kOnHeaders;
  13. var kOnHeadersComplete;
  14. var kOnMessageComplete;
  15. var kOnBody;
  16. if (mode === 'normal' || mode === 'modern') {
  17. HTTPParser = process.binding('http_parser').HTTPParser;
  18. methods = HTTPParser.methods;
  19. // v6
  20. if (!methods)
  21. methods = process.binding('http_parser').methods;
  22. reverseMethods = {};
  23. methods.forEach(function(method, index) {
  24. reverseMethods[method] = index;
  25. });
  26. kOnHeaders = HTTPParser.kOnHeaders | 0;
  27. kOnHeadersComplete = HTTPParser.kOnHeadersComplete | 0;
  28. kOnMessageComplete = HTTPParser.kOnMessageComplete | 0;
  29. kOnBody = HTTPParser.kOnBody | 0;
  30. } else {
  31. kOnHeaders = 'onHeaders';
  32. kOnHeadersComplete = 'onHeadersComplete';
  33. kOnMessageComplete = 'onMessageComplete';
  34. kOnBody = 'onBody';
  35. }
  36. function Deceiver(socket, options) {
  37. this.socket = socket;
  38. this.options = options || {};
  39. this.isClient = this.options.isClient;
  40. }
  41. module.exports = Deceiver;
  42. Deceiver.create = function create(stream, options) {
  43. return new Deceiver(stream, options);
  44. };
  45. Deceiver.prototype._toHeaderList = function _toHeaderList(object) {
  46. var out = [];
  47. var keys = Object.keys(object);
  48. for (var i = 0; i < keys.length; i++)
  49. out.push(keys[i], object[keys[i]]);
  50. return out;
  51. };
  52. Deceiver.prototype._isUpgrade = function _isUpgrade(request) {
  53. return request.method === 'CONNECT' ||
  54. request.headers.upgrade ||
  55. request.headers.connection &&
  56. /(^|\W)upgrade(\W|$)/i.test(request.headers.connection);
  57. };
  58. // TODO(indutny): support CONNECT
  59. if (mode === 'modern') {
  60. /*
  61. function parserOnHeadersComplete(versionMajor, versionMinor, headers, method,
  62. url, statusCode, statusMessage, upgrade,
  63. shouldKeepAlive) {
  64. */
  65. Deceiver.prototype.emitRequest = function emitRequest(request) {
  66. var parser = this.socket.parser;
  67. assert(parser, 'No parser present');
  68. parser.execute = null;
  69. var self = this;
  70. var method = reverseMethods[request.method];
  71. parser.execute = function execute() {
  72. self._skipExecute(this);
  73. this[kOnHeadersComplete](1,
  74. 1,
  75. self._toHeaderList(request.headers),
  76. method,
  77. request.path,
  78. 0,
  79. '',
  80. self._isUpgrade(request),
  81. true);
  82. return 0;
  83. };
  84. this._emitEmpty();
  85. };
  86. Deceiver.prototype.emitResponse = function emitResponse(response) {
  87. var parser = this.socket.parser;
  88. assert(parser, 'No parser present');
  89. parser.execute = null;
  90. var self = this;
  91. parser.execute = function execute() {
  92. self._skipExecute(this);
  93. this[kOnHeadersComplete](1,
  94. 1,
  95. self._toHeaderList(response.headers),
  96. response.path,
  97. response.code,
  98. response.status,
  99. response.reason || '',
  100. self._isUpgrade(response),
  101. true);
  102. return 0;
  103. };
  104. this._emitEmpty();
  105. };
  106. } else {
  107. /*
  108. `function parserOnHeadersComplete(info) {`
  109. info = { .versionMajor, .versionMinor, .url, .headers, .method,
  110. .statusCode, .statusMessage, .upgrade, .shouldKeepAlive }
  111. */
  112. Deceiver.prototype.emitRequest = function emitRequest(request) {
  113. var parser = this.socket.parser;
  114. assert(parser, 'No parser present');
  115. var method = request.method;
  116. if (reverseMethods)
  117. method = reverseMethods[method];
  118. var info = {
  119. versionMajor: 1,
  120. versionMinor: 1,
  121. url: request.path,
  122. headers: this._toHeaderList(request.headers),
  123. method: method,
  124. statusCode: 0,
  125. statusMessage: '',
  126. upgrade: this._isUpgrade(request),
  127. shouldKeepAlive: true
  128. };
  129. var self = this;
  130. parser.execute = function execute() {
  131. self._skipExecute(this);
  132. this[kOnHeadersComplete](info);
  133. return 0;
  134. };
  135. this._emitEmpty();
  136. };
  137. Deceiver.prototype.emitResponse = function emitResponse(response) {
  138. var parser = this.socket.parser;
  139. assert(parser, 'No parser present');
  140. var info = {
  141. versionMajor: 1,
  142. versionMinor: 1,
  143. url: response.path,
  144. headers: this._toHeaderList(response.headers),
  145. method: false,
  146. statusCode: response.status,
  147. statusMessage: response.reason || '',
  148. upgrade: this._isUpgrade(response),
  149. shouldKeepAlive: true
  150. };
  151. var self = this;
  152. parser.execute = function execute() {
  153. self._skipExecute(this);
  154. this[kOnHeadersComplete](info);
  155. return 0;
  156. };
  157. this._emitEmpty();
  158. };
  159. }
  160. Deceiver.prototype._skipExecute = function _skipExecute(parser) {
  161. var self = this;
  162. var oldExecute = parser.constructor.prototype.execute;
  163. var oldFinish = parser.constructor.prototype.finish;
  164. parser.execute = null;
  165. parser.finish = null;
  166. parser.execute = function execute(buffer, start, len) {
  167. // Parser reuse
  168. if (this.socket !== self.socket) {
  169. this.execute = oldExecute;
  170. this.finish = oldFinish;
  171. return this.execute(buffer, start, len);
  172. }
  173. if (start !== undefined)
  174. buffer = buffer.slice(start, start + len);
  175. self.emitBody(buffer);
  176. return len;
  177. };
  178. parser.finish = function finish() {
  179. // Parser reuse
  180. if (this.socket !== self.socket) {
  181. this.execute = oldExecute;
  182. this.finish = oldFinish;
  183. return this.finish();
  184. }
  185. this.execute = oldExecute;
  186. this.finish = oldFinish;
  187. self.emitMessageComplete();
  188. };
  189. };
  190. Deceiver.prototype.emitBody = function emitBody(buffer) {
  191. var parser = this.socket.parser;
  192. assert(parser, 'No parser present');
  193. parser[kOnBody](buffer, 0, buffer.length);
  194. };
  195. Deceiver.prototype._emitEmpty = function _emitEmpty() {
  196. // Emit data to force out handling of UPGRADE
  197. var empty = new Buffer(0);
  198. if (this.socket.ondata)
  199. this.socket.ondata(empty, 0, 0);
  200. else
  201. this.socket.emit('data', empty);
  202. };
  203. Deceiver.prototype.emitMessageComplete = function emitMessageComplete() {
  204. var parser = this.socket.parser;
  205. assert(parser, 'No parser present');
  206. parser[kOnMessageComplete]();
  207. };