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.
		
		
		
		
		
			
		
			
				
					111 lines
				
				2.9 KiB
			
		
		
			
		
	
	
					111 lines
				
				2.9 KiB
			| 
											3 years ago
										 | var EventEmitter = require('events').EventEmitter, | ||
|  |     inherits = require('util').inherits; | ||
|  | 
 | ||
|  | var StreamSearch = require('streamsearch'); | ||
|  | 
 | ||
|  | var B_DCRLF = new Buffer('\r\n\r\n'), | ||
|  |     RE_CRLF = /\r\n/g, | ||
|  |     RE_HDR = /^([^:]+):[ \t]?([\x00-\xFF]+)?$/, | ||
|  |     MAX_HEADER_PAIRS = 2000, // from node's http.js
 | ||
|  |     MAX_HEADER_SIZE = 80 * 1024; // from node's http_parser
 | ||
|  | 
 | ||
|  | function HeaderParser(cfg) { | ||
|  |   EventEmitter.call(this); | ||
|  | 
 | ||
|  |   var self = this; | ||
|  |   this.nread = 0; | ||
|  |   this.maxed = false; | ||
|  |   this.npairs = 0; | ||
|  |   this.maxHeaderPairs = (cfg && typeof cfg.maxHeaderPairs === 'number' | ||
|  |                          ? cfg.maxHeaderPairs | ||
|  |                          : MAX_HEADER_PAIRS); | ||
|  |   this.buffer = ''; | ||
|  |   this.header = {}; | ||
|  |   this.finished = false; | ||
|  |   this.ss = new StreamSearch(B_DCRLF); | ||
|  |   this.ss.on('info', function(isMatch, data, start, end) { | ||
|  |     if (data && !self.maxed) { | ||
|  |       if (self.nread + (end - start) > MAX_HEADER_SIZE) { | ||
|  |         end = (MAX_HEADER_SIZE - self.nread); | ||
|  |         self.nread = MAX_HEADER_SIZE; | ||
|  |       } else | ||
|  |         self.nread += (end - start); | ||
|  | 
 | ||
|  |       if (self.nread === MAX_HEADER_SIZE) | ||
|  |         self.maxed = true; | ||
|  | 
 | ||
|  |       self.buffer += data.toString('binary', start, end); | ||
|  |     } | ||
|  |     if (isMatch) | ||
|  |       self._finish(); | ||
|  |   }); | ||
|  | } | ||
|  | inherits(HeaderParser, EventEmitter); | ||
|  | 
 | ||
|  | HeaderParser.prototype.push = function(data) { | ||
|  |   var r = this.ss.push(data); | ||
|  |   if (this.finished) | ||
|  |     return r; | ||
|  | }; | ||
|  | 
 | ||
|  | HeaderParser.prototype.reset = function() { | ||
|  |   this.finished = false; | ||
|  |   this.buffer = ''; | ||
|  |   this.header = {}; | ||
|  |   this.ss.reset(); | ||
|  | }; | ||
|  | 
 | ||
|  | HeaderParser.prototype._finish = function() { | ||
|  |   if (this.buffer) | ||
|  |     this._parseHeader(); | ||
|  |   this.ss.matches = this.ss.maxMatches; | ||
|  |   var header = this.header; | ||
|  |   this.header = {}; | ||
|  |   this.buffer = ''; | ||
|  |   this.finished = true; | ||
|  |   this.nread = this.npairs = 0; | ||
|  |   this.maxed = false; | ||
|  |   this.emit('header', header); | ||
|  | }; | ||
|  | 
 | ||
|  | HeaderParser.prototype._parseHeader = function() { | ||
|  |   if (this.npairs === this.maxHeaderPairs) | ||
|  |     return; | ||
|  | 
 | ||
|  |   var lines = this.buffer.split(RE_CRLF), len = lines.length, m, h, | ||
|  |       modded = false; | ||
|  | 
 | ||
|  |   for (var i = 0; i < len; ++i) { | ||
|  |     if (lines[i].length === 0) | ||
|  |       continue; | ||
|  |     if (lines[i][0] === '\t' || lines[i][0] === ' ') { | ||
|  |       // folded header content
 | ||
|  |       // RFC2822 says to just remove the CRLF and not the whitespace following
 | ||
|  |       // it, so we follow the RFC and include the leading whitespace ...
 | ||
|  |       this.header[h][this.header[h].length - 1] += lines[i]; | ||
|  |     } else { | ||
|  |       m = RE_HDR.exec(lines[i]); | ||
|  |       if (m) { | ||
|  |         h = m[1].toLowerCase(); | ||
|  |         if (m[2]) { | ||
|  |           if (this.header[h] === undefined) | ||
|  |             this.header[h] = [m[2]]; | ||
|  |           else | ||
|  |             this.header[h].push(m[2]); | ||
|  |         } else | ||
|  |           this.header[h] = ['']; | ||
|  |         if (++this.npairs === this.maxHeaderPairs) | ||
|  |           break; | ||
|  |       } else { | ||
|  |         this.buffer = lines[i]; | ||
|  |         modded = true; | ||
|  |         break; | ||
|  |       } | ||
|  |     } | ||
|  |   } | ||
|  |   if (!modded) | ||
|  |     this.buffer = ''; | ||
|  | }; | ||
|  | 
 | ||
|  | module.exports = HeaderParser; |