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.
135 lines
3.2 KiB
135 lines
3.2 KiB
'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;
|
|
|