Code coverage report for lib/_http_common.js

Statements: 98.04% (100 / 102)      Branches: 84.21% (32 / 38)      Functions: 100% (8 / 8)      Lines: 98.02% (99 / 101)      Ignored: none     

All files » lib/ » _http_common.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200    173 173   173 173 173 173   173 173   173 173 173 173   173 173 173 173             173   394   225   394             173     3812   3812 7 7     3812 705 705     3812 3812 3812 3812 3812   3812     3812 3810   3812   3812   3111     701 701     3812   3812   3812       3801     3810         173 6349 6349     6349     6349     6349 3220 3220 3220 164       173 3784 3784   3784 3784   3784 3784 3784 3784 3784       3784       3784       173 1111   1111 1111             1111 1111 1111 1111   1111   173                   173 2467 2467 2467 2467 2467 2467 2467 2467   2467   2467 764   2467 2460     173     173 335       173 2467 2467   173      
(function () { 'use strict';
 
const FreeList = require('internal/freelist').FreeList;
const HTTPParser = process.binding('http_parser').HTTPParser;
 
const incoming = require('_http_incoming');
const IncomingMessage = incoming.IncomingMessage;
const readStart = incoming.readStart;
const readStop = incoming.readStop;
 
const debug = require('util').debuglog('http');
exports.debug = debug;
 
exports.CRLF = '\r\n';
exports.chunkExpression = /chunk/i;
exports.continueExpression = /100-continue/i;
exports.methods = HTTPParser.methods;
 
const kOnHeaders = HTTPParser.kOnHeaders | 0;
const kOnHeadersComplete = HTTPParser.kOnHeadersComplete | 0;
const kOnBody = HTTPParser.kOnBody | 0;
const kOnMessageComplete = HTTPParser.kOnMessageComplete | 0;
 
// Only called in the slow case where slow means
// that the request headers were either fragmented
// across multiple TCP packets or too large to be
// processed in a single run. This method is also
// called to process trailing HTTP headers.
function parserOnHeaders(headers, url) {
  // Once we exceeded headers limit - stop collecting them
  if (this.maxHeaderPairs <= 0 ||
      this._headers.length < this.maxHeaderPairs) {
    this._headers = this._headers.concat(headers);
  }
  this._url += url;
}
 
// `headers` and `url` are set only if .onHeaders() has not been called for
// this request.
// `url` is not set for response parsers but that's not applicable here since
// all our parsers are request parsers.
function parserOnHeadersComplete(versionMajor, versionMinor, headers, method,
                                 url, statusCode, statusMessage, upgrade,
                                 shouldKeepAlive) {
  var parser = this;
 
  if (!headers) {
    headers = parser._headers;
    parser._headers = [];
  }
 
  if (!url) {
    url = parser._url;
    parser._url = '';
  }
 
  parser.incoming = new IncomingMessage(parser.socket);
  parser.incoming.httpVersionMajor = versionMajor;
  parser.incoming.httpVersionMinor = versionMinor;
  parser.incoming.httpVersion = versionMajor + '.' + versionMinor;
  parser.incoming.url = url;
 
  var n = headers.length;
 
  // If parser.maxHeaderPairs <= 0 assume that there's no limit.
  if (parser.maxHeaderPairs > 0)
    n = Math.min(n, parser.maxHeaderPairs);
 
  parser.incoming._addHeaderLines(headers, n);
 
  if (typeof method === 'number') {
    // server only
    parser.incoming.method = HTTPParser.methods[method];
  } else {
    // client only
    parser.incoming.statusCode = statusCode;
    parser.incoming.statusMessage = statusMessage;
  }
 
  parser.incoming.upgrade = upgrade;
 
  var skipBody = false; // response to HEAD or CONNECT
 
  if (!upgrade) {
    // For upgraded connections and CONNECT method request, we'll emit this
    // after parser.execute so that we can capture the first part of the new
    // protocol.
    skipBody = parser.onIncoming(parser.incoming, shouldKeepAlive);
  }
 
  return skipBody;
}
 
// XXX This is a mess.
// TODO: http.Parser should be a Writable emits request/response events.
function parserOnBody(b, start, len) {
  var parser = this;
  var stream = parser.incoming;
 
  // if the stream has already been removed, then drop it.
  Iif (!stream)
    return;
 
  var socket = stream.socket;
 
  // pretend this was the result of a stream._read call.
  if (len > 0 && !stream._dumped) {
    var slice = b.slice(start, start + len);
    var ret = stream.push(slice);
    if (!ret)
      readStop(socket);
  }
}
 
function parserOnMessageComplete() {
  var parser = this;
  var stream = parser.incoming;
 
  Eif (stream) {
    stream.complete = true;
    // Emit any trailing headers.
    var headers = parser._headers;
    Eif (headers) {
      parser.incoming._addHeaderLines(headers, headers.length);
      parser._headers = [];
      parser._url = '';
    }
 
    // For emit end event
    stream.push(null);
  }
 
  // force to read the next incoming message
  readStart(parser.socket);
}
 
 
var parsers = new FreeList('parsers', 1000, function() {
  var parser = new HTTPParser(HTTPParser.REQUEST);
 
  parser._headers = [];
  parser._url = '';
 
  // Only called in the slow case where slow means
  // that the request headers were either fragmented
  // across multiple TCP packets or too large to be
  // processed in a single run. This method is also
  // called to process trailing HTTP headers.
  parser[kOnHeaders] = parserOnHeaders;
  parser[kOnHeadersComplete] = parserOnHeadersComplete;
  parser[kOnBody] = parserOnBody;
  parser[kOnMessageComplete] = parserOnMessageComplete;
 
  return parser;
});
exports.parsers = parsers;
 
 
// Free the parser and also break any links that it
// might have to any other things.
// TODO: All parser data should be attached to a
// single object, so that it can be easily cleaned
// up by doing `parser.data = {}`, which should
// be done in FreeList.free.  `parsers.free(parser)`
// should be all that is needed.
function freeParser(parser, req, socket) {
  Eif (parser) {
    parser._headers = [];
    parser.onIncoming = null;
    Eif (parser.socket)
      parser.socket.parser = null;
    parser.socket = null;
    parser.incoming = null;
    Iif (parsers.free(parser) === false)
      parser.close();
    parser = null;
  }
  if (req) {
    req.parser = null;
  }
  if (socket) {
    socket.parser = null;
  }
}
exports.freeParser = freeParser;
 
 
function ondrain() {
  if (this._httpMessage) this._httpMessage.emit('drain');
}
 
 
function httpSocketSetup(socket) {
  socket.removeListener('drain', ondrain);
  socket.on('drain', ondrain);
}
exports.httpSocketSetup = httpSocketSetup;
 
}());