| 'use strict'; | 
|   | 
| var NodeHTTPParser = require('http-parser-js').HTTPParser, | 
|     Buffer         = require('safe-buffer').Buffer; | 
|   | 
| var TYPES = { | 
|   request:  NodeHTTPParser.REQUEST  || 'request', | 
|   response: NodeHTTPParser.RESPONSE || 'response' | 
| }; | 
|   | 
| var HttpParser = function(type) { | 
|   this._type     = type; | 
|   this._parser   = new NodeHTTPParser(TYPES[type]); | 
|   this._complete = false; | 
|   this.headers   = {}; | 
|   | 
|   var current = null, | 
|       self    = this; | 
|   | 
|   this._parser.onHeaderField = function(b, start, length) { | 
|     current = b.toString('utf8', start, start + length).toLowerCase(); | 
|   }; | 
|   | 
|   this._parser.onHeaderValue = function(b, start, length) { | 
|     var value = b.toString('utf8', start, start + length); | 
|   | 
|     if (self.headers.hasOwnProperty(current)) | 
|       self.headers[current] += ', ' + value; | 
|     else | 
|       self.headers[current] = value; | 
|   }; | 
|   | 
|   this._parser.onHeadersComplete = this._parser[NodeHTTPParser.kOnHeadersComplete] = | 
|   function(majorVersion, minorVersion, headers, method, pathname, statusCode) { | 
|     var info = arguments[0]; | 
|   | 
|     if (typeof info === 'object') { | 
|       method     = info.method; | 
|       pathname   = info.url; | 
|       statusCode = info.statusCode; | 
|       headers    = info.headers; | 
|     } | 
|   | 
|     self.method     = (typeof method === 'number') ? HttpParser.METHODS[method] : method; | 
|     self.statusCode = statusCode; | 
|     self.url        = pathname; | 
|   | 
|     if (!headers) return; | 
|   | 
|     for (var i = 0, n = headers.length, key, value; i < n; i += 2) { | 
|       key   = headers[i].toLowerCase(); | 
|       value = headers[i+1]; | 
|       if (self.headers.hasOwnProperty(key)) | 
|         self.headers[key] += ', ' + value; | 
|       else | 
|         self.headers[key] = value; | 
|     } | 
|   | 
|     self._complete = true; | 
|   }; | 
| }; | 
|   | 
| HttpParser.METHODS = { | 
|   0:  'DELETE', | 
|   1:  'GET', | 
|   2:  'HEAD', | 
|   3:  'POST', | 
|   4:  'PUT', | 
|   5:  'CONNECT', | 
|   6:  'OPTIONS', | 
|   7:  'TRACE', | 
|   8:  'COPY', | 
|   9:  'LOCK', | 
|   10: 'MKCOL', | 
|   11: 'MOVE', | 
|   12: 'PROPFIND', | 
|   13: 'PROPPATCH', | 
|   14: 'SEARCH', | 
|   15: 'UNLOCK', | 
|   16: 'BIND', | 
|   17: 'REBIND', | 
|   18: 'UNBIND', | 
|   19: 'ACL', | 
|   20: 'REPORT', | 
|   21: 'MKACTIVITY', | 
|   22: 'CHECKOUT', | 
|   23: 'MERGE', | 
|   24: 'M-SEARCH', | 
|   25: 'NOTIFY', | 
|   26: 'SUBSCRIBE', | 
|   27: 'UNSUBSCRIBE', | 
|   28: 'PATCH', | 
|   29: 'PURGE', | 
|   30: 'MKCALENDAR', | 
|   31: 'LINK', | 
|   32: 'UNLINK' | 
| }; | 
|   | 
| var VERSION = process.version | 
|   ? process.version.match(/[0-9]+/g).map(function(n) { return parseInt(n, 10) }) | 
|   : []; | 
|   | 
| if (VERSION[0] === 0 && VERSION[1] === 12) { | 
|   HttpParser.METHODS[16] = 'REPORT'; | 
|   HttpParser.METHODS[17] = 'MKACTIVITY'; | 
|   HttpParser.METHODS[18] = 'CHECKOUT'; | 
|   HttpParser.METHODS[19] = 'MERGE'; | 
|   HttpParser.METHODS[20] = 'M-SEARCH'; | 
|   HttpParser.METHODS[21] = 'NOTIFY'; | 
|   HttpParser.METHODS[22] = 'SUBSCRIBE'; | 
|   HttpParser.METHODS[23] = 'UNSUBSCRIBE'; | 
|   HttpParser.METHODS[24] = 'PATCH'; | 
|   HttpParser.METHODS[25] = 'PURGE'; | 
| } | 
|   | 
| HttpParser.prototype.isComplete = function() { | 
|   return this._complete; | 
| }; | 
|   | 
| HttpParser.prototype.parse = function(chunk) { | 
|   var consumed = this._parser.execute(chunk, 0, chunk.length); | 
|   | 
|   if (typeof consumed !== 'number') { | 
|     this.error     = consumed; | 
|     this._complete = true; | 
|     return; | 
|   } | 
|   | 
|   if (this._complete) | 
|     this.body = (consumed < chunk.length) | 
|               ? chunk.slice(consumed) | 
|               : Buffer.alloc(0); | 
| }; | 
|   | 
| module.exports = HttpParser; |