[6a3a178] | 1 | 'use strict';
|
---|
| 2 |
|
---|
| 3 | var NodeHTTPParser = require('http-parser-js').HTTPParser,
|
---|
| 4 | Buffer = require('safe-buffer').Buffer;
|
---|
| 5 |
|
---|
| 6 | var TYPES = {
|
---|
| 7 | request: NodeHTTPParser.REQUEST || 'request',
|
---|
| 8 | response: NodeHTTPParser.RESPONSE || 'response'
|
---|
| 9 | };
|
---|
| 10 |
|
---|
| 11 | var HttpParser = function(type) {
|
---|
| 12 | this._type = type;
|
---|
| 13 | this._parser = new NodeHTTPParser(TYPES[type]);
|
---|
| 14 | this._complete = false;
|
---|
| 15 | this.headers = {};
|
---|
| 16 |
|
---|
| 17 | var current = null,
|
---|
| 18 | self = this;
|
---|
| 19 |
|
---|
| 20 | this._parser.onHeaderField = function(b, start, length) {
|
---|
| 21 | current = b.toString('utf8', start, start + length).toLowerCase();
|
---|
| 22 | };
|
---|
| 23 |
|
---|
| 24 | this._parser.onHeaderValue = function(b, start, length) {
|
---|
| 25 | var value = b.toString('utf8', start, start + length);
|
---|
| 26 |
|
---|
| 27 | if (self.headers.hasOwnProperty(current))
|
---|
| 28 | self.headers[current] += ', ' + value;
|
---|
| 29 | else
|
---|
| 30 | self.headers[current] = value;
|
---|
| 31 | };
|
---|
| 32 |
|
---|
| 33 | this._parser.onHeadersComplete = this._parser[NodeHTTPParser.kOnHeadersComplete] =
|
---|
| 34 | function(majorVersion, minorVersion, headers, method, pathname, statusCode) {
|
---|
| 35 | var info = arguments[0];
|
---|
| 36 |
|
---|
| 37 | if (typeof info === 'object') {
|
---|
| 38 | method = info.method;
|
---|
| 39 | pathname = info.url;
|
---|
| 40 | statusCode = info.statusCode;
|
---|
| 41 | headers = info.headers;
|
---|
| 42 | }
|
---|
| 43 |
|
---|
| 44 | self.method = (typeof method === 'number') ? HttpParser.METHODS[method] : method;
|
---|
| 45 | self.statusCode = statusCode;
|
---|
| 46 | self.url = pathname;
|
---|
| 47 |
|
---|
| 48 | if (!headers) return;
|
---|
| 49 |
|
---|
| 50 | for (var i = 0, n = headers.length, key, value; i < n; i += 2) {
|
---|
| 51 | key = headers[i].toLowerCase();
|
---|
| 52 | value = headers[i+1];
|
---|
| 53 | if (self.headers.hasOwnProperty(key))
|
---|
| 54 | self.headers[key] += ', ' + value;
|
---|
| 55 | else
|
---|
| 56 | self.headers[key] = value;
|
---|
| 57 | }
|
---|
| 58 |
|
---|
| 59 | self._complete = true;
|
---|
| 60 | };
|
---|
| 61 | };
|
---|
| 62 |
|
---|
| 63 | HttpParser.METHODS = {
|
---|
| 64 | 0: 'DELETE',
|
---|
| 65 | 1: 'GET',
|
---|
| 66 | 2: 'HEAD',
|
---|
| 67 | 3: 'POST',
|
---|
| 68 | 4: 'PUT',
|
---|
| 69 | 5: 'CONNECT',
|
---|
| 70 | 6: 'OPTIONS',
|
---|
| 71 | 7: 'TRACE',
|
---|
| 72 | 8: 'COPY',
|
---|
| 73 | 9: 'LOCK',
|
---|
| 74 | 10: 'MKCOL',
|
---|
| 75 | 11: 'MOVE',
|
---|
| 76 | 12: 'PROPFIND',
|
---|
| 77 | 13: 'PROPPATCH',
|
---|
| 78 | 14: 'SEARCH',
|
---|
| 79 | 15: 'UNLOCK',
|
---|
| 80 | 16: 'BIND',
|
---|
| 81 | 17: 'REBIND',
|
---|
| 82 | 18: 'UNBIND',
|
---|
| 83 | 19: 'ACL',
|
---|
| 84 | 20: 'REPORT',
|
---|
| 85 | 21: 'MKACTIVITY',
|
---|
| 86 | 22: 'CHECKOUT',
|
---|
| 87 | 23: 'MERGE',
|
---|
| 88 | 24: 'M-SEARCH',
|
---|
| 89 | 25: 'NOTIFY',
|
---|
| 90 | 26: 'SUBSCRIBE',
|
---|
| 91 | 27: 'UNSUBSCRIBE',
|
---|
| 92 | 28: 'PATCH',
|
---|
| 93 | 29: 'PURGE',
|
---|
| 94 | 30: 'MKCALENDAR',
|
---|
| 95 | 31: 'LINK',
|
---|
| 96 | 32: 'UNLINK'
|
---|
| 97 | };
|
---|
| 98 |
|
---|
| 99 | var VERSION = process.version
|
---|
| 100 | ? process.version.match(/[0-9]+/g).map(function(n) { return parseInt(n, 10) })
|
---|
| 101 | : [];
|
---|
| 102 |
|
---|
| 103 | if (VERSION[0] === 0 && VERSION[1] === 12) {
|
---|
| 104 | HttpParser.METHODS[16] = 'REPORT';
|
---|
| 105 | HttpParser.METHODS[17] = 'MKACTIVITY';
|
---|
| 106 | HttpParser.METHODS[18] = 'CHECKOUT';
|
---|
| 107 | HttpParser.METHODS[19] = 'MERGE';
|
---|
| 108 | HttpParser.METHODS[20] = 'M-SEARCH';
|
---|
| 109 | HttpParser.METHODS[21] = 'NOTIFY';
|
---|
| 110 | HttpParser.METHODS[22] = 'SUBSCRIBE';
|
---|
| 111 | HttpParser.METHODS[23] = 'UNSUBSCRIBE';
|
---|
| 112 | HttpParser.METHODS[24] = 'PATCH';
|
---|
| 113 | HttpParser.METHODS[25] = 'PURGE';
|
---|
| 114 | }
|
---|
| 115 |
|
---|
| 116 | HttpParser.prototype.isComplete = function() {
|
---|
| 117 | return this._complete;
|
---|
| 118 | };
|
---|
| 119 |
|
---|
| 120 | HttpParser.prototype.parse = function(chunk) {
|
---|
| 121 | var consumed = this._parser.execute(chunk, 0, chunk.length);
|
---|
| 122 |
|
---|
| 123 | if (typeof consumed !== 'number') {
|
---|
| 124 | this.error = consumed;
|
---|
| 125 | this._complete = true;
|
---|
| 126 | return;
|
---|
| 127 | }
|
---|
| 128 |
|
---|
| 129 | if (this._complete)
|
---|
| 130 | this.body = (consumed < chunk.length)
|
---|
| 131 | ? chunk.slice(consumed)
|
---|
| 132 | : Buffer.alloc(0);
|
---|
| 133 | };
|
---|
| 134 |
|
---|
| 135 | module.exports = HttpParser;
|
---|