http_parser.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. 'use strict';
  2. var NodeHTTPParser = process.binding('http_parser').HTTPParser,
  3. version = NodeHTTPParser.RESPONSE ? 6 : 4;
  4. var HttpParser = function(type) {
  5. if (type === 'request')
  6. this._parser = new NodeHTTPParser(NodeHTTPParser.REQUEST || 'request');
  7. else
  8. this._parser = new NodeHTTPParser(NodeHTTPParser.RESPONSE || 'response');
  9. this._type = type;
  10. this._complete = false;
  11. this.headers = {};
  12. var current = null,
  13. self = this;
  14. this._parser.onHeaderField = function(b, start, length) {
  15. current = b.toString('utf8', start, start + length).toLowerCase();
  16. };
  17. this._parser.onHeaderValue = function(b, start, length) {
  18. var value = b.toString('utf8', start, start + length);
  19. if (self.headers.hasOwnProperty(current))
  20. self.headers[current] += ', ' + value;
  21. else
  22. self.headers[current] = value;
  23. };
  24. this._parser.onHeadersComplete = this._parser[NodeHTTPParser.kOnHeadersComplete] =
  25. function(majorVersion, minorVersion, headers, method, pathname, statusCode) {
  26. var info = arguments[0];
  27. if (typeof info === 'object') {
  28. method = info.method;
  29. pathname = info.url;
  30. statusCode = info.statusCode;
  31. headers = info.headers;
  32. }
  33. self.method = (typeof method === 'number') ? HttpParser.METHODS[method] : method;
  34. self.statusCode = statusCode;
  35. self.url = pathname;
  36. if (!headers) return;
  37. for (var i = 0, n = headers.length, key, value; i < n; i += 2) {
  38. key = headers[i].toLowerCase();
  39. value = headers[i+1];
  40. if (self.headers.hasOwnProperty(key))
  41. self.headers[key] += ', ' + value;
  42. else
  43. self.headers[key] = value;
  44. }
  45. self._complete = true;
  46. };
  47. };
  48. HttpParser.METHODS = {
  49. 0: 'DELETE',
  50. 1: 'GET',
  51. 2: 'HEAD',
  52. 3: 'POST',
  53. 4: 'PUT',
  54. 5: 'CONNECT',
  55. 6: 'OPTIONS',
  56. 7: 'TRACE',
  57. 8: 'COPY',
  58. 9: 'LOCK',
  59. 10: 'MKCOL',
  60. 11: 'MOVE',
  61. 12: 'PROPFIND',
  62. 13: 'PROPPATCH',
  63. 14: 'SEARCH',
  64. 15: 'UNLOCK',
  65. 16: 'REPORT',
  66. 17: 'MKACTIVITY',
  67. 18: 'CHECKOUT',
  68. 19: 'MERGE',
  69. 24: 'PATCH'
  70. };
  71. HttpParser.prototype.isComplete = function() {
  72. return this._complete;
  73. };
  74. HttpParser.prototype.parse = function(chunk) {
  75. var offset = (version < 6) ? 1 : 0,
  76. consumed = this._parser.execute(chunk, 0, chunk.length) + offset;
  77. if (this._complete)
  78. this.body = (consumed < chunk.length)
  79. ? chunk.slice(consumed)
  80. : new Buffer(0);
  81. };
  82. module.exports = HttpParser;