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