'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;