136 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			136 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| '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;
 |