PageRenderTime 110ms CodeModel.GetById 4ms app.highlight 92ms RepoModel.GetById 1ms app.codeStats 1ms

/node_modules/commonjs-everywhere/node/lib/http.js

https://github.com/flochtililoch/automate
JavaScript | 2115 lines | 1457 code | 340 blank | 318 comment | 357 complexity | c0fc369423153be411271a3c02227ea5 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1// Copyright Joyent, Inc. and other Node contributors.
   2//
   3// Permission is hereby granted, free of charge, to any person obtaining a
   4// copy of this software and associated documentation files (the
   5// "Software"), to deal in the Software without restriction, including
   6// without limitation the rights to use, copy, modify, merge, publish,
   7// distribute, sublicense, and/or sell copies of the Software, and to permit
   8// persons to whom the Software is furnished to do so, subject to the
   9// following conditions:
  10//
  11// The above copyright notice and this permission notice shall be included
  12// in all copies or substantial portions of the Software.
  13//
  14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  15// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  16// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  17// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  18// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  19// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  20// USE OR OTHER DEALINGS IN THE SOFTWARE.
  21
  22var util = require('util');
  23var net = require('net');
  24var Stream = require('stream');
  25var timers = require('timers');
  26var url = require('url');
  27var EventEmitter = require('events').EventEmitter;
  28var FreeList = require('freelist').FreeList;
  29var HTTPParser = process.binding('http_parser').HTTPParser;
  30var assert = require('assert').ok;
  31
  32var debug;
  33if (process.env.NODE_DEBUG && /http/.test(process.env.NODE_DEBUG)) {
  34  debug = function(x) { console.error('HTTP: %s', x); };
  35} else {
  36  debug = function() { };
  37}
  38
  39function readStart(socket) {
  40  if (!socket || !socket._handle || !socket._handle.readStart) return;
  41  socket._handle.readStart();
  42}
  43
  44function readStop(socket) {
  45  if (!socket || !socket._handle || !socket._handle.readStop) return;
  46  socket._handle.readStop();
  47}
  48
  49// Only called in the slow case where slow means
  50// that the request headers were either fragmented
  51// across multiple TCP packets or too large to be
  52// processed in a single run. This method is also
  53// called to process trailing HTTP headers.
  54function parserOnHeaders(headers, url) {
  55  // Once we exceeded headers limit - stop collecting them
  56  if (this.maxHeaderPairs <= 0 ||
  57      this._headers.length < this.maxHeaderPairs) {
  58    this._headers = this._headers.concat(headers);
  59  }
  60  this._url += url;
  61}
  62
  63// info.headers and info.url are set only if .onHeaders()
  64// has not been called for this request.
  65//
  66// info.url is not set for response parsers but that's not
  67// applicable here since all our parsers are request parsers.
  68function parserOnHeadersComplete(info) {
  69  var parser = this;
  70  var headers = info.headers;
  71  var url = info.url;
  72
  73  if (!headers) {
  74    headers = parser._headers;
  75    parser._headers = [];
  76  }
  77
  78  if (!url) {
  79    url = parser._url;
  80    parser._url = '';
  81  }
  82
  83  parser.incoming = new IncomingMessage(parser.socket);
  84  parser.incoming.httpVersionMajor = info.versionMajor;
  85  parser.incoming.httpVersionMinor = info.versionMinor;
  86  parser.incoming.httpVersion = info.versionMajor + '.' + info.versionMinor;
  87  parser.incoming.url = url;
  88
  89  var n = headers.length;
  90
  91  // If parser.maxHeaderPairs <= 0 - assume that there're no limit
  92  if (parser.maxHeaderPairs > 0) {
  93    n = Math.min(n, parser.maxHeaderPairs);
  94  }
  95
  96  for (var i = 0; i < n; i += 2) {
  97    var k = headers[i];
  98    var v = headers[i + 1];
  99    parser.incoming._addHeaderLine(k, v);
 100  }
 101
 102
 103  if (info.method) {
 104    // server only
 105    parser.incoming.method = info.method;
 106  } else {
 107    // client only
 108    parser.incoming.statusCode = info.statusCode;
 109    // CHECKME dead code? we're always a request parser
 110  }
 111
 112  parser.incoming.upgrade = info.upgrade;
 113
 114  var skipBody = false; // response to HEAD or CONNECT
 115
 116  if (!info.upgrade) {
 117    // For upgraded connections and CONNECT method request,
 118    // we'll emit this after parser.execute
 119    // so that we can capture the first part of the new protocol
 120    skipBody = parser.onIncoming(parser.incoming, info.shouldKeepAlive);
 121  }
 122
 123  return skipBody;
 124}
 125
 126// XXX This is a mess.
 127// TODO: http.Parser should be a Writable emits request/response events.
 128function parserOnBody(b, start, len) {
 129  var parser = this;
 130  var stream = parser.incoming;
 131
 132  // if the stream has already been removed, then drop it.
 133  if (!stream)
 134    return;
 135
 136  var socket = stream.socket;
 137
 138  // pretend this was the result of a stream._read call.
 139  if (len > 0 && !stream._dumped) {
 140    var slice = b.slice(start, start + len);
 141    var ret = stream.push(slice);
 142    if (!ret)
 143      readStop(socket);
 144  }
 145}
 146
 147function parserOnMessageComplete() {
 148  var parser = this;
 149  var stream = parser.incoming;
 150
 151  if (stream) {
 152    stream.complete = true;
 153    // Emit any trailing headers.
 154    var headers = parser._headers;
 155    if (headers) {
 156      for (var i = 0, n = headers.length; i < n; i += 2) {
 157        var k = headers[i];
 158        var v = headers[i + 1];
 159        parser.incoming._addHeaderLine(k, v);
 160      }
 161      parser._headers = [];
 162      parser._url = '';
 163    }
 164
 165    if (!stream.upgrade)
 166      // For upgraded connections, also emit this after parser.execute
 167      stream.push(null);
 168  }
 169
 170  if (stream && !parser.incoming._pendings.length) {
 171    // For emit end event
 172    stream.push(null);
 173  }
 174
 175  if (parser.socket.readable) {
 176    // force to read the next incoming message
 177    readStart(parser.socket);
 178  }
 179}
 180
 181
 182var parsers = new FreeList('parsers', 1000, function() {
 183  var parser = new HTTPParser(HTTPParser.REQUEST);
 184
 185  parser._headers = [];
 186  parser._url = '';
 187
 188  // Only called in the slow case where slow means
 189  // that the request headers were either fragmented
 190  // across multiple TCP packets or too large to be
 191  // processed in a single run. This method is also
 192  // called to process trailing HTTP headers.
 193  parser.onHeaders = parserOnHeaders;
 194  parser.onHeadersComplete = parserOnHeadersComplete;
 195  parser.onBody = parserOnBody;
 196  parser.onMessageComplete = parserOnMessageComplete;
 197
 198  return parser;
 199});
 200exports.parsers = parsers;
 201
 202
 203var CRLF = '\r\n';
 204var STATUS_CODES = exports.STATUS_CODES = {
 205  100 : 'Continue',
 206  101 : 'Switching Protocols',
 207  102 : 'Processing',                 // RFC 2518, obsoleted by RFC 4918
 208  200 : 'OK',
 209  201 : 'Created',
 210  202 : 'Accepted',
 211  203 : 'Non-Authoritative Information',
 212  204 : 'No Content',
 213  205 : 'Reset Content',
 214  206 : 'Partial Content',
 215  207 : 'Multi-Status',               // RFC 4918
 216  300 : 'Multiple Choices',
 217  301 : 'Moved Permanently',
 218  302 : 'Moved Temporarily',
 219  303 : 'See Other',
 220  304 : 'Not Modified',
 221  305 : 'Use Proxy',
 222  307 : 'Temporary Redirect',
 223  400 : 'Bad Request',
 224  401 : 'Unauthorized',
 225  402 : 'Payment Required',
 226  403 : 'Forbidden',
 227  404 : 'Not Found',
 228  405 : 'Method Not Allowed',
 229  406 : 'Not Acceptable',
 230  407 : 'Proxy Authentication Required',
 231  408 : 'Request Time-out',
 232  409 : 'Conflict',
 233  410 : 'Gone',
 234  411 : 'Length Required',
 235  412 : 'Precondition Failed',
 236  413 : 'Request Entity Too Large',
 237  414 : 'Request-URI Too Large',
 238  415 : 'Unsupported Media Type',
 239  416 : 'Requested Range Not Satisfiable',
 240  417 : 'Expectation Failed',
 241  418 : 'I\'m a teapot',              // RFC 2324
 242  422 : 'Unprocessable Entity',       // RFC 4918
 243  423 : 'Locked',                     // RFC 4918
 244  424 : 'Failed Dependency',          // RFC 4918
 245  425 : 'Unordered Collection',       // RFC 4918
 246  426 : 'Upgrade Required',           // RFC 2817
 247  428 : 'Precondition Required',      // RFC 6585
 248  429 : 'Too Many Requests',          // RFC 6585
 249  431 : 'Request Header Fields Too Large',// RFC 6585
 250  500 : 'Internal Server Error',
 251  501 : 'Not Implemented',
 252  502 : 'Bad Gateway',
 253  503 : 'Service Unavailable',
 254  504 : 'Gateway Time-out',
 255  505 : 'HTTP Version Not Supported',
 256  506 : 'Variant Also Negotiates',    // RFC 2295
 257  507 : 'Insufficient Storage',       // RFC 4918
 258  509 : 'Bandwidth Limit Exceeded',
 259  510 : 'Not Extended',               // RFC 2774
 260  511 : 'Network Authentication Required' // RFC 6585
 261};
 262
 263
 264var connectionExpression = /Connection/i;
 265var transferEncodingExpression = /Transfer-Encoding/i;
 266var closeExpression = /close/i;
 267var chunkExpression = /chunk/i;
 268var contentLengthExpression = /Content-Length/i;
 269var dateExpression = /Date/i;
 270var expectExpression = /Expect/i;
 271var continueExpression = /100-continue/i;
 272
 273var dateCache;
 274function utcDate() {
 275  if (!dateCache) {
 276    var d = new Date();
 277    dateCache = d.toUTCString();
 278    timers.enroll(utcDate, 1000 - d.getMilliseconds());
 279    timers._unrefActive(utcDate);
 280  }
 281  return dateCache;
 282}
 283utcDate._onTimeout = function() {
 284  dateCache = undefined;
 285};
 286
 287
 288/* Abstract base class for ServerRequest and ClientResponse. */
 289function IncomingMessage(socket) {
 290  Stream.Readable.call(this);
 291
 292  // XXX This implementation is kind of all over the place
 293  // When the parser emits body chunks, they go in this list.
 294  // _read() pulls them out, and when it finds EOF, it ends.
 295
 296  this.socket = socket;
 297  this.connection = socket;
 298
 299  this.httpVersion = null;
 300  this.complete = false;
 301  this.headers = {};
 302  this.trailers = {};
 303
 304  this.readable = true;
 305
 306  this._pendings = [];
 307  this._pendingIndex = 0;
 308
 309  // request (server) only
 310  this.url = '';
 311  this.method = null;
 312
 313  // response (client) only
 314  this.statusCode = null;
 315  this.client = this.socket;
 316
 317  // flag for backwards compatibility grossness.
 318  this._consuming = false;
 319
 320  // flag for when we decide that this message cannot possibly be
 321  // read by the user, so there's no point continuing to handle it.
 322  this._dumped = false;
 323}
 324util.inherits(IncomingMessage, Stream.Readable);
 325
 326
 327exports.IncomingMessage = IncomingMessage;
 328
 329
 330IncomingMessage.prototype.setTimeout = function(msecs, callback) {
 331  if (callback)
 332    this.on('timeout', callback);
 333  this.socket.setTimeout(msecs);
 334};
 335
 336
 337IncomingMessage.prototype.read = function(n) {
 338  this._consuming = true;
 339  this.read = Stream.Readable.prototype.read;
 340  return this.read(n);
 341};
 342
 343
 344IncomingMessage.prototype._read = function(n) {
 345  // We actually do almost nothing here, because the parserOnBody
 346  // function fills up our internal buffer directly.  However, we
 347  // do need to unpause the underlying socket so that it flows.
 348  if (!this.socket.readable)
 349    this.push(null);
 350  else
 351    readStart(this.socket);
 352};
 353
 354
 355// It's possible that the socket will be destroyed, and removed from
 356// any messages, before ever calling this.  In that case, just skip
 357// it, since something else is destroying this connection anyway.
 358IncomingMessage.prototype.destroy = function(error) {
 359  if (this.socket)
 360    this.socket.destroy(error);
 361};
 362
 363
 364// Add the given (field, value) pair to the message
 365//
 366// Per RFC2616, section 4.2 it is acceptable to join multiple instances of the
 367// same header with a ', ' if the header in question supports specification of
 368// multiple values this way. If not, we declare the first instance the winner
 369// and drop the second. Extended header fields (those beginning with 'x-') are
 370// always joined.
 371IncomingMessage.prototype._addHeaderLine = function(field, value) {
 372  var dest = this.complete ? this.trailers : this.headers;
 373
 374  field = field.toLowerCase();
 375  switch (field) {
 376    // Array headers:
 377    case 'set-cookie':
 378      if (dest[field] !== undefined) {
 379        dest[field].push(value);
 380      } else {
 381        dest[field] = [value];
 382      }
 383      break;
 384
 385    // Comma separate. Maybe make these arrays?
 386    case 'accept':
 387    case 'accept-charset':
 388    case 'accept-encoding':
 389    case 'accept-language':
 390    case 'connection':
 391    case 'cookie':
 392    case 'pragma':
 393    case 'link':
 394    case 'www-authenticate':
 395    case 'proxy-authenticate':
 396    case 'sec-websocket-extensions':
 397    case 'sec-websocket-protocol':
 398      if (dest[field] !== undefined) {
 399        dest[field] += ', ' + value;
 400      } else {
 401        dest[field] = value;
 402      }
 403      break;
 404
 405
 406    default:
 407      if (field.slice(0, 2) == 'x-') {
 408        // except for x-
 409        if (dest[field] !== undefined) {
 410          dest[field] += ', ' + value;
 411        } else {
 412          dest[field] = value;
 413        }
 414      } else {
 415        // drop duplicates
 416        if (dest[field] === undefined) dest[field] = value;
 417      }
 418      break;
 419  }
 420};
 421
 422
 423// Call this instead of resume() if we want to just
 424// dump all the data to /dev/null
 425IncomingMessage.prototype._dump = function() {
 426  if (!this._dumped) {
 427    this._dumped = true;
 428    if (this.socket.parser) this.socket.parser.incoming = null;
 429    this.push(null);
 430    readStart(this.socket);
 431    this.read();
 432  }
 433};
 434
 435
 436function OutgoingMessage() {
 437  Stream.call(this);
 438
 439  this.output = [];
 440  this.outputEncodings = [];
 441
 442  this.writable = true;
 443
 444  this._last = false;
 445  this.chunkedEncoding = false;
 446  this.shouldKeepAlive = true;
 447  this.useChunkedEncodingByDefault = true;
 448  this.sendDate = false;
 449
 450  this._hasBody = true;
 451  this._trailer = '';
 452
 453  this.finished = false;
 454  this._hangupClose = false;
 455
 456  this.socket = null;
 457  this.connection = null;
 458}
 459util.inherits(OutgoingMessage, Stream);
 460
 461
 462exports.OutgoingMessage = OutgoingMessage;
 463
 464
 465OutgoingMessage.prototype.setTimeout = function(msecs, callback) {
 466  if (callback)
 467    this.on('timeout', callback);
 468  if (!this.socket) {
 469    this.once('socket', function(socket) {
 470      socket.setTimeout(msecs);
 471    });
 472  } else
 473    this.socket.setTimeout(msecs);
 474};
 475
 476
 477// It's possible that the socket will be destroyed, and removed from
 478// any messages, before ever calling this.  In that case, just skip
 479// it, since something else is destroying this connection anyway.
 480OutgoingMessage.prototype.destroy = function(error) {
 481  if (this.socket)
 482    this.socket.destroy(error);
 483  else
 484    this.once('socket', function(socket) {
 485      socket.destroy(error);
 486    });
 487};
 488
 489
 490// This abstract either writing directly to the socket or buffering it.
 491OutgoingMessage.prototype._send = function(data, encoding) {
 492  // This is a shameful hack to get the headers and first body chunk onto
 493  // the same packet. Future versions of Node are going to take care of
 494  // this at a lower level and in a more general way.
 495  if (!this._headerSent) {
 496    if (typeof data === 'string') {
 497      data = this._header + data;
 498    } else {
 499      this.output.unshift(this._header);
 500      this.outputEncodings.unshift('ascii');
 501    }
 502    this._headerSent = true;
 503  }
 504  return this._writeRaw(data, encoding);
 505};
 506
 507
 508OutgoingMessage.prototype._writeRaw = function(data, encoding) {
 509  if (data.length === 0) {
 510    return true;
 511  }
 512
 513  if (this.connection &&
 514      this.connection._httpMessage === this &&
 515      this.connection.writable &&
 516      !this.connection.destroyed) {
 517    // There might be pending data in the this.output buffer.
 518    while (this.output.length) {
 519      if (!this.connection.writable) {
 520        this._buffer(data, encoding);
 521        return false;
 522      }
 523      var c = this.output.shift();
 524      var e = this.outputEncodings.shift();
 525      this.connection.write(c, e);
 526    }
 527
 528    // Directly write to socket.
 529    return this.connection.write(data, encoding);
 530  } else if (this.connection && this.connection.destroyed) {
 531    // The socket was destroyed.  If we're still trying to write to it,
 532    // then we haven't gotten the 'close' event yet.
 533    return false;
 534  } else {
 535    // buffer, as long as we're not destroyed.
 536    this._buffer(data, encoding);
 537    return false;
 538  }
 539};
 540
 541
 542OutgoingMessage.prototype._buffer = function(data, encoding) {
 543  if (data.length === 0) return;
 544
 545  var length = this.output.length;
 546
 547  if (length === 0 || typeof data != 'string') {
 548    this.output.push(data);
 549    this.outputEncodings.push(encoding);
 550    return false;
 551  }
 552
 553  var lastEncoding = this.outputEncodings[length - 1];
 554  var lastData = this.output[length - 1];
 555
 556  if ((encoding && lastEncoding === encoding) ||
 557      (!encoding && data.constructor === lastData.constructor)) {
 558    this.output[length - 1] = lastData + data;
 559    return false;
 560  }
 561
 562  this.output.push(data);
 563  this.outputEncodings.push(encoding);
 564
 565  return false;
 566};
 567
 568
 569OutgoingMessage.prototype._storeHeader = function(firstLine, headers) {
 570  // firstLine in the case of request is: 'GET /index.html HTTP/1.1\r\n'
 571  // in the case of response it is: 'HTTP/1.1 200 OK\r\n'
 572  var state = {
 573    sentConnectionHeader: false,
 574    sentContentLengthHeader: false,
 575    sentTransferEncodingHeader: false,
 576    sentDateHeader: false,
 577    sentExpect: false,
 578    messageHeader: firstLine
 579  };
 580
 581  var field, value;
 582  var self = this;
 583
 584  if (headers) {
 585    var keys = Object.keys(headers);
 586    var isArray = (Array.isArray(headers));
 587    var field, value;
 588
 589    for (var i = 0, l = keys.length; i < l; i++) {
 590      var key = keys[i];
 591      if (isArray) {
 592        field = headers[key][0];
 593        value = headers[key][1];
 594      } else {
 595        field = key;
 596        value = headers[key];
 597      }
 598
 599      if (Array.isArray(value)) {
 600        for (var j = 0; j < value.length; j++) {
 601          storeHeader(this, state, field, value[j]);
 602        }
 603      } else {
 604        storeHeader(this, state, field, value);
 605      }
 606    }
 607  }
 608
 609  // Date header
 610  if (this.sendDate == true && state.sentDateHeader == false) {
 611    state.messageHeader += 'Date: ' + utcDate() + CRLF;
 612  }
 613
 614  // Force the connection to close when the response is a 204 No Content or
 615  // a 304 Not Modified and the user has set a "Transfer-Encoding: chunked"
 616  // header.
 617  //
 618  // RFC 2616 mandates that 204 and 304 responses MUST NOT have a body but
 619  // node.js used to send out a zero chunk anyway to accommodate clients
 620  // that don't have special handling for those responses.
 621  //
 622  // It was pointed out that this might confuse reverse proxies to the point
 623  // of creating security liabilities, so suppress the zero chunk and force
 624  // the connection to close.
 625  var statusCode = this.statusCode;
 626  if ((statusCode == 204 || statusCode === 304) &&
 627      this.chunkedEncoding === true) {
 628    debug(statusCode + ' response should not use chunked encoding,' +
 629          ' closing connection.');
 630    this.chunkedEncoding = false;
 631    this.shouldKeepAlive = false;
 632  }
 633
 634  // keep-alive logic
 635  if (state.sentConnectionHeader === false) {
 636    var shouldSendKeepAlive = this.shouldKeepAlive &&
 637        (state.sentContentLengthHeader ||
 638         this.useChunkedEncodingByDefault ||
 639         this.agent);
 640    if (shouldSendKeepAlive) {
 641      state.messageHeader += 'Connection: keep-alive\r\n';
 642    } else {
 643      this._last = true;
 644      state.messageHeader += 'Connection: close\r\n';
 645    }
 646  }
 647
 648  if (state.sentContentLengthHeader == false &&
 649      state.sentTransferEncodingHeader == false) {
 650    if (this._hasBody) {
 651      if (this.useChunkedEncodingByDefault) {
 652        state.messageHeader += 'Transfer-Encoding: chunked\r\n';
 653        this.chunkedEncoding = true;
 654      } else {
 655        this._last = true;
 656      }
 657    } else {
 658      // Make sure we don't end the 0\r\n\r\n at the end of the message.
 659      this.chunkedEncoding = false;
 660    }
 661  }
 662
 663  this._header = state.messageHeader + CRLF;
 664  this._headerSent = false;
 665
 666  // wait until the first body chunk, or close(), is sent to flush,
 667  // UNLESS we're sending Expect: 100-continue.
 668  if (state.sentExpect) this._send('');
 669};
 670
 671function storeHeader(self, state, field, value) {
 672  // Protect against response splitting. The if statement is there to
 673  // minimize the performance impact in the common case.
 674  if (/[\r\n]/.test(value))
 675    value = value.replace(/[\r\n]+[ \t]*/g, '');
 676
 677  state.messageHeader += field + ': ' + value + CRLF;
 678
 679  if (connectionExpression.test(field)) {
 680    state.sentConnectionHeader = true;
 681    if (closeExpression.test(value)) {
 682      self._last = true;
 683    } else {
 684      self.shouldKeepAlive = true;
 685    }
 686
 687  } else if (transferEncodingExpression.test(field)) {
 688    state.sentTransferEncodingHeader = true;
 689    if (chunkExpression.test(value)) self.chunkedEncoding = true;
 690
 691  } else if (contentLengthExpression.test(field)) {
 692    state.sentContentLengthHeader = true;
 693  } else if (dateExpression.test(field)) {
 694    state.sentDateHeader = true;
 695  } else if (expectExpression.test(field)) {
 696    state.sentExpect = true;
 697  }
 698}
 699
 700
 701OutgoingMessage.prototype.setHeader = function(name, value) {
 702  if (arguments.length < 2) {
 703    throw new Error('`name` and `value` are required for setHeader().');
 704  }
 705
 706  if (this._header) {
 707    throw new Error('Can\'t set headers after they are sent.');
 708  }
 709
 710  var key = name.toLowerCase();
 711  this._headers = this._headers || {};
 712  this._headerNames = this._headerNames || {};
 713  this._headers[key] = value;
 714  this._headerNames[key] = name;
 715};
 716
 717
 718OutgoingMessage.prototype.getHeader = function(name) {
 719  if (arguments.length < 1) {
 720    throw new Error('`name` is required for getHeader().');
 721  }
 722
 723  if (!this._headers) return;
 724
 725  var key = name.toLowerCase();
 726  return this._headers[key];
 727};
 728
 729
 730OutgoingMessage.prototype.removeHeader = function(name) {
 731  if (arguments.length < 1) {
 732    throw new Error('`name` is required for removeHeader().');
 733  }
 734
 735  if (this._header) {
 736    throw new Error('Can\'t remove headers after they are sent.');
 737  }
 738
 739  if (!this._headers) return;
 740
 741  var key = name.toLowerCase();
 742  delete this._headers[key];
 743  delete this._headerNames[key];
 744};
 745
 746
 747OutgoingMessage.prototype._renderHeaders = function() {
 748  if (this._header) {
 749    throw new Error('Can\'t render headers after they are sent to the client.');
 750  }
 751
 752  if (!this._headers) return {};
 753
 754  var headers = {};
 755  var keys = Object.keys(this._headers);
 756  for (var i = 0, l = keys.length; i < l; i++) {
 757    var key = keys[i];
 758    headers[this._headerNames[key]] = this._headers[key];
 759  }
 760  return headers;
 761};
 762
 763
 764Object.defineProperty(OutgoingMessage.prototype, 'headersSent', {
 765  configurable: true,
 766  enumerable: true,
 767  get: function() { return !!this._header; }
 768});
 769
 770
 771OutgoingMessage.prototype.write = function(chunk, encoding) {
 772  if (!this._header) {
 773    this._implicitHeader();
 774  }
 775
 776  if (!this._hasBody) {
 777    debug('This type of response MUST NOT have a body. ' +
 778          'Ignoring write() calls.');
 779    return true;
 780  }
 781
 782  if (typeof chunk !== 'string' && !Buffer.isBuffer(chunk)) {
 783    throw new TypeError('first argument must be a string or Buffer');
 784  }
 785
 786  // If we get an empty string or buffer, then just do nothing, and
 787  // signal the user to keep writing.
 788  if (chunk.length === 0) return true;
 789
 790  // TODO(bnoordhuis) Temporary optimization hack, remove in v0.11. We only
 791  // want to convert the buffer when we're sending:
 792  //
 793  //   a) Transfer-Encoding chunks, because it lets us pack the chunk header
 794  //      and the chunk into a single write(), or
 795  //
 796  //   b) the first chunk of a fixed-length request, because it lets us pack
 797  //      the request headers and the chunk into a single write().
 798  //
 799  // Converting to strings is expensive, CPU-wise, but reducing the number
 800  // of write() calls more than makes up for that because we're dramatically
 801  // reducing the number of TCP roundtrips.
 802  if (chunk instanceof Buffer && (this.chunkedEncoding || !this._headerSent)) {
 803    chunk = chunk.toString('binary');
 804    encoding = 'binary';
 805  }
 806
 807  var len, ret;
 808  if (this.chunkedEncoding) {
 809    if (typeof(chunk) === 'string' &&
 810        encoding !== 'hex' &&
 811        encoding !== 'base64') {
 812      len = Buffer.byteLength(chunk, encoding);
 813      chunk = len.toString(16) + CRLF + chunk + CRLF;
 814      ret = this._send(chunk, encoding);
 815    } else {
 816      // buffer, or a non-toString-friendly encoding
 817      len = chunk.length;
 818      this._send(len.toString(16) + CRLF);
 819      this._send(chunk, encoding);
 820      ret = this._send(CRLF);
 821    }
 822  } else {
 823    ret = this._send(chunk, encoding);
 824  }
 825
 826  debug('write ret = ' + ret);
 827  return ret;
 828};
 829
 830
 831OutgoingMessage.prototype.addTrailers = function(headers) {
 832  this._trailer = '';
 833  var keys = Object.keys(headers);
 834  var isArray = (Array.isArray(headers));
 835  var field, value;
 836  for (var i = 0, l = keys.length; i < l; i++) {
 837    var key = keys[i];
 838    if (isArray) {
 839      field = headers[key][0];
 840      value = headers[key][1];
 841    } else {
 842      field = key;
 843      value = headers[key];
 844    }
 845
 846    this._trailer += field + ': ' + value + CRLF;
 847  }
 848};
 849
 850
 851var zero_chunk_buf = new Buffer('\r\n0\r\n');
 852var crlf_buf = new Buffer('\r\n');
 853
 854
 855OutgoingMessage.prototype.end = function(data, encoding) {
 856  if (this.finished) {
 857    return false;
 858  }
 859  if (!this._header) {
 860    this._implicitHeader();
 861  }
 862
 863  if (data && !this._hasBody) {
 864    debug('This type of response MUST NOT have a body. ' +
 865          'Ignoring data passed to end().');
 866    data = false;
 867  }
 868
 869  var ret;
 870
 871  var hot = this._headerSent === false &&
 872            (data && data.length > 0) &&
 873            this.output.length === 0 &&
 874            this.connection &&
 875            this.connection.writable &&
 876            this.connection._httpMessage === this;
 877
 878  // The benefits of the hot-path optimization below start to fall
 879  // off when the buffer size gets up near 128KB, because the cost
 880  // of the copy is more than the cost of the extra write() call.
 881  // Switch to the write/end method at that point.  Heuristics and
 882  // magic numbers are awful, but slow http responses are worse.
 883  if (hot && Buffer.isBuffer(data) && data.length > 120 * 1024)
 884    hot = false;
 885
 886  if (hot) {
 887    // Hot path. They're doing
 888    //   res.writeHead();
 889    //   res.end(blah);
 890    // HACKY.
 891
 892    if (typeof data === 'string') {
 893      if (this.chunkedEncoding) {
 894        var l = Buffer.byteLength(data, encoding).toString(16);
 895        ret = this.connection.write(this._header + l + CRLF +
 896                                    data + '\r\n0\r\n' +
 897                                    this._trailer + '\r\n', encoding);
 898      } else {
 899        ret = this.connection.write(this._header + data, encoding);
 900      }
 901    } else if (Buffer.isBuffer(data)) {
 902      if (this.chunkedEncoding) {
 903        var chunk_size = data.length.toString(16);
 904
 905        // Skip expensive Buffer.byteLength() calls; only ISO-8859-1 characters
 906        // are allowed in HTTP headers. Therefore:
 907        //
 908        //   this._header.length == Buffer.byteLength(this._header.length)
 909        //   this._trailer.length == Buffer.byteLength(this._trailer.length)
 910        //
 911        var header_len = this._header.length;
 912        var chunk_size_len = chunk_size.length;
 913        var data_len = data.length;
 914        var trailer_len = this._trailer.length;
 915
 916        var len = header_len +
 917                  chunk_size_len +
 918                  2 + // '\r\n'.length
 919                  data_len +
 920                  5 + // '\r\n0\r\n'.length
 921                  trailer_len +
 922                  2;  // '\r\n'.length
 923
 924        var buf = new Buffer(len);
 925        var off = 0;
 926
 927        buf.write(this._header, off, header_len, 'ascii');
 928        off += header_len;
 929
 930        buf.write(chunk_size, off, chunk_size_len, 'ascii');
 931        off += chunk_size_len;
 932
 933        crlf_buf.copy(buf, off);
 934        off += 2;
 935
 936        data.copy(buf, off);
 937        off += data_len;
 938
 939        zero_chunk_buf.copy(buf, off);
 940        off += 5;
 941
 942        if (trailer_len > 0) {
 943          buf.write(this._trailer, off, trailer_len, 'ascii');
 944          off += trailer_len;
 945        }
 946
 947        crlf_buf.copy(buf, off);
 948
 949        ret = this.connection.write(buf);
 950      } else {
 951        var header_len = this._header.length;
 952        var buf = new Buffer(header_len + data.length);
 953        buf.write(this._header, 0, header_len, 'ascii');
 954        data.copy(buf, header_len);
 955        ret = this.connection.write(buf);
 956      }
 957    } else {
 958      throw new TypeError('first argument must be a string or Buffer');
 959    }
 960    this._headerSent = true;
 961
 962  } else if (data) {
 963    // Normal body write.
 964    ret = this.write(data, encoding);
 965  }
 966
 967  if (!hot) {
 968    if (this.chunkedEncoding) {
 969      ret = this._send('0\r\n' + this._trailer + '\r\n'); // Last chunk.
 970    } else {
 971      // Force a flush, HACK.
 972      ret = this._send('');
 973    }
 974  }
 975
 976  this.finished = true;
 977
 978  // There is the first message on the outgoing queue, and we've sent
 979  // everything to the socket.
 980  debug('outgoing message end.');
 981  if (this.output.length === 0 && this.connection._httpMessage === this) {
 982    this._finish();
 983  }
 984
 985  return ret;
 986};
 987
 988
 989OutgoingMessage.prototype._finish = function() {
 990  assert(this.connection);
 991  if (this instanceof ServerResponse) {
 992    DTRACE_HTTP_SERVER_RESPONSE(this.connection);
 993    COUNTER_HTTP_SERVER_RESPONSE();
 994  } else {
 995    assert(this instanceof ClientRequest);
 996    DTRACE_HTTP_CLIENT_REQUEST(this, this.connection);
 997    COUNTER_HTTP_CLIENT_REQUEST();
 998  }
 999  this.emit('finish');
1000};
1001
1002
1003OutgoingMessage.prototype._flush = function() {
1004  // This logic is probably a bit confusing. Let me explain a bit:
1005  //
1006  // In both HTTP servers and clients it is possible to queue up several
1007  // outgoing messages. This is easiest to imagine in the case of a client.
1008  // Take the following situation:
1009  //
1010  //    req1 = client.request('GET', '/');
1011  //    req2 = client.request('POST', '/');
1012  //
1013  // When the user does
1014  //
1015  //   req2.write('hello world\n');
1016  //
1017  // it's possible that the first request has not been completely flushed to
1018  // the socket yet. Thus the outgoing messages need to be prepared to queue
1019  // up data internally before sending it on further to the socket's queue.
1020  //
1021  // This function, outgoingFlush(), is called by both the Server and Client
1022  // to attempt to flush any pending messages out to the socket.
1023
1024  if (!this.socket) return;
1025
1026  var ret;
1027  while (this.output.length) {
1028
1029    if (!this.socket.writable) return; // XXX Necessary?
1030
1031    var data = this.output.shift();
1032    var encoding = this.outputEncodings.shift();
1033
1034    ret = this.socket.write(data, encoding);
1035  }
1036
1037  if (this.finished) {
1038    // This is a queue to the server or client to bring in the next this.
1039    this._finish();
1040  } else if (ret) {
1041    // This is necessary to prevent https from breaking
1042    this.emit('drain');
1043  }
1044};
1045
1046
1047
1048
1049function ServerResponse(req) {
1050  OutgoingMessage.call(this);
1051
1052  if (req.method === 'HEAD') this._hasBody = false;
1053
1054  this.sendDate = true;
1055
1056  if (req.httpVersionMajor < 1 || req.httpVersionMinor < 1) {
1057    this.useChunkedEncodingByDefault = chunkExpression.test(req.headers.te);
1058    this.shouldKeepAlive = false;
1059  }
1060}
1061util.inherits(ServerResponse, OutgoingMessage);
1062
1063
1064exports.ServerResponse = ServerResponse;
1065
1066ServerResponse.prototype.statusCode = 200;
1067
1068function onServerResponseClose() {
1069  // EventEmitter.emit makes a copy of the 'close' listeners array before
1070  // calling the listeners. detachSocket() unregisters onServerResponseClose
1071  // but if detachSocket() is called, directly or indirectly, by a 'close'
1072  // listener, onServerResponseClose is still in that copy of the listeners
1073  // array. That is, in the example below, b still gets called even though
1074  // it's been removed by a:
1075  //
1076  //   var obj = new events.EventEmitter;
1077  //   obj.on('event', a);
1078  //   obj.on('event', b);
1079  //   function a() { obj.removeListener('event', b) }
1080  //   function b() { throw "BAM!" }
1081  //   obj.emit('event');  // throws
1082  //
1083  // Ergo, we need to deal with stale 'close' events and handle the case
1084  // where the ServerResponse object has already been deconstructed.
1085  // Fortunately, that requires only a single if check. :-)
1086  if (this._httpMessage) this._httpMessage.emit('close');
1087}
1088
1089ServerResponse.prototype.assignSocket = function(socket) {
1090  assert(!socket._httpMessage);
1091  socket._httpMessage = this;
1092  socket.on('close', onServerResponseClose);
1093  this.socket = socket;
1094  this.connection = socket;
1095  this.emit('socket', socket);
1096  this._flush();
1097};
1098
1099ServerResponse.prototype.detachSocket = function(socket) {
1100  assert(socket._httpMessage == this);
1101  socket.removeListener('close', onServerResponseClose);
1102  socket._httpMessage = null;
1103  this.socket = this.connection = null;
1104};
1105
1106ServerResponse.prototype.writeContinue = function() {
1107  this._writeRaw('HTTP/1.1 100 Continue' + CRLF + CRLF, 'ascii');
1108  this._sent100 = true;
1109};
1110
1111ServerResponse.prototype._implicitHeader = function() {
1112  this.writeHead(this.statusCode);
1113};
1114
1115ServerResponse.prototype.writeHead = function(statusCode) {
1116  var reasonPhrase, headers, headerIndex;
1117
1118  if (typeof arguments[1] == 'string') {
1119    reasonPhrase = arguments[1];
1120    headerIndex = 2;
1121  } else {
1122    reasonPhrase = STATUS_CODES[statusCode] || 'unknown';
1123    headerIndex = 1;
1124  }
1125  this.statusCode = statusCode;
1126
1127  var obj = arguments[headerIndex];
1128
1129  if (obj && this._headers) {
1130    // Slow-case: when progressive API and header fields are passed.
1131    headers = this._renderHeaders();
1132
1133    if (Array.isArray(obj)) {
1134      // handle array case
1135      // TODO: remove when array is no longer accepted
1136      var field;
1137      for (var i = 0, len = obj.length; i < len; ++i) {
1138        field = obj[i][0];
1139        if (headers[field] !== undefined) {
1140          obj.push([field, headers[field]]);
1141        }
1142      }
1143      headers = obj;
1144
1145    } else {
1146      // handle object case
1147      var keys = Object.keys(obj);
1148      for (var i = 0; i < keys.length; i++) {
1149        var k = keys[i];
1150        if (k) headers[k] = obj[k];
1151      }
1152    }
1153  } else if (this._headers) {
1154    // only progressive api is used
1155    headers = this._renderHeaders();
1156  } else {
1157    // only writeHead() called
1158    headers = obj;
1159  }
1160
1161  var statusLine = 'HTTP/1.1 ' + statusCode.toString() + ' ' +
1162                   reasonPhrase + CRLF;
1163
1164  if (statusCode === 204 || statusCode === 304 ||
1165      (100 <= statusCode && statusCode <= 199)) {
1166    // RFC 2616, 10.2.5:
1167    // The 204 response MUST NOT include a message-body, and thus is always
1168    // terminated by the first empty line after the header fields.
1169    // RFC 2616, 10.3.5:
1170    // The 304 response MUST NOT contain a message-body, and thus is always
1171    // terminated by the first empty line after the header fields.
1172    // RFC 2616, 10.1 Informational 1xx:
1173    // This class of status code indicates a provisional response,
1174    // consisting only of the Status-Line and optional headers, and is
1175    // terminated by an empty line.
1176    this._hasBody = false;
1177  }
1178
1179  // don't keep alive connections where the client expects 100 Continue
1180  // but we sent a final status; they may put extra bytes on the wire.
1181  if (this._expect_continue && !this._sent100) {
1182    this.shouldKeepAlive = false;
1183  }
1184
1185  this._storeHeader(statusLine, headers);
1186};
1187
1188ServerResponse.prototype.writeHeader = function() {
1189  this.writeHead.apply(this, arguments);
1190};
1191
1192
1193// New Agent code.
1194
1195// The largest departure from the previous implementation is that
1196// an Agent instance holds connections for a variable number of host:ports.
1197// Surprisingly, this is still API compatible as far as third parties are
1198// concerned. The only code that really notices the difference is the
1199// request object.
1200
1201// Another departure is that all code related to HTTP parsing is in
1202// ClientRequest.onSocket(). The Agent is now *strictly*
1203// concerned with managing a connection pool.
1204
1205function Agent(options) {
1206  EventEmitter.call(this);
1207
1208  var self = this;
1209  self.options = options || {};
1210  self.requests = {};
1211  self.sockets = {};
1212  self.maxSockets = self.options.maxSockets || Agent.defaultMaxSockets;
1213  self.on('free', function(socket, host, port, localAddress) {
1214    var name = host + ':' + port;
1215    if (localAddress) {
1216      name += ':' + localAddress;
1217    }
1218
1219    if (!socket.destroyed &&
1220        self.requests[name] && self.requests[name].length) {
1221      self.requests[name].shift().onSocket(socket);
1222      if (self.requests[name].length === 0) {
1223        // don't leak
1224        delete self.requests[name];
1225      }
1226    } else {
1227      // If there are no pending requests just destroy the
1228      // socket and it will get removed from the pool. This
1229      // gets us out of timeout issues and allows us to
1230      // default to Connection:keep-alive.
1231      socket.destroy();
1232    }
1233  });
1234  self.createConnection = net.createConnection;
1235}
1236util.inherits(Agent, EventEmitter);
1237exports.Agent = Agent;
1238
1239Agent.defaultMaxSockets = 5;
1240
1241Agent.prototype.defaultPort = 80;
1242Agent.prototype.addRequest = function(req, host, port, localAddress) {
1243  var name = host + ':' + port;
1244  if (localAddress) {
1245    name += ':' + localAddress;
1246  }
1247  if (!this.sockets[name]) {
1248    this.sockets[name] = [];
1249  }
1250  if (this.sockets[name].length < this.maxSockets) {
1251    // If we are under maxSockets create a new one.
1252    req.onSocket(this.createSocket(name, host, port, localAddress, req));
1253  } else {
1254    // We are over limit so we'll add it to the queue.
1255    if (!this.requests[name]) {
1256      this.requests[name] = [];
1257    }
1258    this.requests[name].push(req);
1259  }
1260};
1261Agent.prototype.createSocket = function(name, host, port, localAddress, req) {
1262  var self = this;
1263  var options = util._extend({}, self.options);
1264  options.port = port;
1265  options.host = host;
1266  options.localAddress = localAddress;
1267
1268  options.servername = host;
1269  if (req) {
1270    var hostHeader = req.getHeader('host');
1271    if (hostHeader) {
1272      options.servername = hostHeader.replace(/:.*$/, '');
1273    }
1274  }
1275
1276  var s = self.createConnection(options);
1277  if (!self.sockets[name]) {
1278    self.sockets[name] = [];
1279  }
1280  this.sockets[name].push(s);
1281  var onFree = function() {
1282    self.emit('free', s, host, port, localAddress);
1283  }
1284  s.on('free', onFree);
1285  var onClose = function(err) {
1286    // This is the only place where sockets get removed from the Agent.
1287    // If you want to remove a socket from the pool, just close it.
1288    // All socket errors end in a close event anyway.
1289    self.removeSocket(s, name, host, port, localAddress);
1290  }
1291  s.on('close', onClose);
1292  var onRemove = function() {
1293    // We need this function for cases like HTTP 'upgrade'
1294    // (defined by WebSockets) where we need to remove a socket from the pool
1295    //  because it'll be locked up indefinitely
1296    self.removeSocket(s, name, host, port, localAddress);
1297    s.removeListener('close', onClose);
1298    s.removeListener('free', onFree);
1299    s.removeListener('agentRemove', onRemove);
1300  }
1301  s.on('agentRemove', onRemove);
1302  return s;
1303};
1304Agent.prototype.removeSocket = function(s, name, host, port, localAddress) {
1305  if (this.sockets[name]) {
1306    var index = this.sockets[name].indexOf(s);
1307    if (index !== -1) {
1308      this.sockets[name].splice(index, 1);
1309      if (this.sockets[name].length === 0) {
1310        // don't leak
1311        delete this.sockets[name];
1312      }
1313    }
1314  }
1315  if (this.requests[name] && this.requests[name].length) {
1316    var req = this.requests[name][0];
1317    // If we have pending requests and a socket gets closed a new one
1318    this.createSocket(name, host, port, localAddress, req).emit('free');
1319  }
1320};
1321
1322var globalAgent = new Agent();
1323exports.globalAgent = globalAgent;
1324
1325
1326function ClientRequest(options, cb) {
1327  var self = this;
1328  OutgoingMessage.call(self);
1329
1330  self.agent = options.agent === undefined ? globalAgent : options.agent;
1331
1332  var defaultPort = options.defaultPort || 80;
1333
1334  var port = options.port || defaultPort;
1335  var host = options.hostname || options.host || 'localhost';
1336
1337  if (options.setHost === undefined) {
1338    var setHost = true;
1339  }
1340
1341  self.socketPath = options.socketPath;
1342
1343  var method = self.method = (options.method || 'GET').toUpperCase();
1344  self.path = options.path || '/';
1345  if (cb) {
1346    self.once('response', cb);
1347  }
1348
1349  if (!Array.isArray(options.headers)) {
1350    if (options.headers) {
1351      var keys = Object.keys(options.headers);
1352      for (var i = 0, l = keys.length; i < l; i++) {
1353        var key = keys[i];
1354        self.setHeader(key, options.headers[key]);
1355      }
1356    }
1357    if (host && !this.getHeader('host') && setHost) {
1358      var hostHeader = host;
1359      if (port && +port !== defaultPort) {
1360        hostHeader += ':' + port;
1361      }
1362      this.setHeader('Host', hostHeader);
1363    }
1364  }
1365
1366  if (options.auth && !this.getHeader('Authorization')) {
1367    //basic auth
1368    this.setHeader('Authorization', 'Basic ' +
1369                   new Buffer(options.auth).toString('base64'));
1370  }
1371
1372  if (method === 'GET' || method === 'HEAD' || method === 'CONNECT') {
1373    self.useChunkedEncodingByDefault = false;
1374  } else {
1375    self.useChunkedEncodingByDefault = true;
1376  }
1377
1378  if (Array.isArray(options.headers)) {
1379    self._storeHeader(self.method + ' ' + self.path + ' HTTP/1.1\r\n',
1380                      options.headers);
1381  } else if (self.getHeader('expect')) {
1382    self._storeHeader(self.method + ' ' + self.path + ' HTTP/1.1\r\n',
1383                      self._renderHeaders());
1384  }
1385  if (self.socketPath) {
1386    self._last = true;
1387    self.shouldKeepAlive = false;
1388    if (options.createConnection) {
1389      self.onSocket(options.createConnection(self.socketPath));
1390    } else {
1391      self.onSocket(net.createConnection(self.socketPath));
1392    }
1393  } else if (self.agent) {
1394    // If there is an agent we should default to Connection:keep-alive.
1395    self._last = false;
1396    self.shouldKeepAlive = true;
1397    self.agent.addRequest(self, host, port, options.localAddress);
1398  } else {
1399    // No agent, default to Connection:close.
1400    self._last = true;
1401    self.shouldKeepAlive = false;
1402    if (options.createConnection) {
1403      options.port = port;
1404      options.host = host;
1405      var conn = options.createConnection(options);
1406    } else {
1407      var conn = net.createConnection({
1408        port: port,
1409        host: host,
1410        localAddress: options.localAddress
1411      });
1412    }
1413    self.onSocket(conn);
1414  }
1415
1416  self._deferToConnect(null, null, function() {
1417    self._flush();
1418    self = null;
1419  });
1420
1421}
1422util.inherits(ClientRequest, OutgoingMessage);
1423
1424exports.ClientRequest = ClientRequest;
1425
1426ClientRequest.prototype._implicitHeader = function() {
1427  this._storeHeader(this.method + ' ' + this.path + ' HTTP/1.1\r\n',
1428                    this._renderHeaders());
1429};
1430
1431ClientRequest.prototype.abort = function() {
1432  // If we're aborting, we don't care about any more response data.
1433  if (this.res)
1434    this.res._dump();
1435  else
1436    this.once('response', function(res) {
1437      res._dump();
1438    });
1439
1440  if (this.socket) {
1441    // in-progress
1442    this.socket.destroy();
1443  } else {
1444    // haven't been assigned a socket yet.
1445    // this could be more efficient, it could
1446    // remove itself from the pending requests
1447    this._deferToConnect('destroy', []);
1448  }
1449};
1450
1451
1452function createHangUpError() {
1453  var error = new Error('socket hang up');
1454  error.code = 'ECONNRESET';
1455  return error;
1456}
1457
1458// Free the parser and also break any links that it
1459// might have to any other things.
1460// TODO: All parser data should be attached to a
1461// single object, so that it can be easily cleaned
1462// up by doing `parser.data = {}`, which should
1463// be done in FreeList.free.  `parsers.free(parser)`
1464// should be all that is needed.
1465function freeParser(parser, req) {
1466  if (parser) {
1467    parser._headers = [];
1468    parser.onIncoming = null;
1469    if (parser.socket) {
1470      parser.socket.onend = null;
1471      parser.socket.ondata = null;
1472      parser.socket.parser = null;
1473    }
1474    parser.socket = null;
1475    parser.incoming = null;
1476    parsers.free(parser);
1477    parser = null;
1478  }
1479  if (req) {
1480    req.parser = null;
1481  }
1482}
1483
1484
1485function socketCloseListener() {
1486  var socket = this;
1487  var parser = socket.parser;
1488  var req = socket._httpMessage;
1489  debug('HTTP socket close');
1490  req.emit('close');
1491  if (req.res && req.res.readable) {
1492    // Socket closed before we emitted 'end' below.
1493    req.res.emit('aborted');
1494    var res = req.res;
1495    res.on('end', function() {
1496      res.emit('close');
1497    });
1498    res.push(null);
1499  } else if (!req.res && !req._hadError) {
1500    // This socket error fired before we started to
1501    // receive a response. The error needs to
1502    // fire on the request.
1503    req.emit('error', createHangUpError());
1504    req._hadError = true;
1505  }
1506
1507  // Too bad.  That output wasn't getting written.
1508  // This is pretty terrible that it doesn't raise an error.
1509  // Fixed better in v0.10
1510  if (req.output)
1511    req.output.length = 0;
1512  if (req.outputEncodings)
1513    req.outputEncodings.length = 0;
1514
1515  if (parser) {
1516    parser.finish();
1517    freeParser(parser, req);
1518  }
1519}
1520
1521function socketErrorListener(err) {
1522  var socket = this;
1523  var parser = socket.parser;
1524  var req = socket._httpMessage;
1525  debug('HTTP SOCKET ERROR: ' + err.message + '\n' + err.stack);
1526
1527  if (req) {
1528    req.emit('error', err);
1529    // For Safety. Some additional errors might fire later on
1530    // and we need to make sure we don't double-fire the error event.
1531    req._hadError = true;
1532  }
1533
1534  if (parser) {
1535    parser.finish();
1536    freeParser(parser, req);
1537  }
1538  socket.destroy();
1539}
1540
1541function socketOnEnd() {
1542  var socket = this;
1543  var req = this._httpMessage;
1544  var parser = this.parser;
1545
1546  if (!req.res) {
1547    // If we don't have a response then we know that the socket
1548    // ended prematurely and we need to emit an error on the request.
1549    req.emit('error', createHangUpError());
1550    req._hadError = true;
1551  }
1552  if (parser) {
1553    parser.finish();
1554    freeParser(parser, req);
1555  }
1556  socket.destroy();
1557}
1558
1559function socketOnData(d, start, end) {
1560  var socket = this;
1561  var req = this._httpMessage;
1562  var parser = this.parser;
1563
1564  var ret = parser.execute(d, start, end - start);
1565  if (ret instanceof Error) {
1566    debug('parse error');
1567    freeParser(parser, req);
1568    socket.destroy();
1569    req.emit('error', ret);
1570    req._hadError = true;
1571  } else if (parser.incoming && parser.incoming.upgrade) {
1572    // Upgrade or CONNECT
1573    var bytesParsed = ret;
1574    var res = parser.incoming;
1575    req.res = res;
1576
1577    socket.ondata = null;
1578    socket.onend = null;
1579    parser.finish();
1580
1581    // This is start + byteParsed
1582    var bodyHead = d.slice(start + bytesParsed, end);
1583
1584    var eventName = req.method === 'CONNECT' ? 'connect' : 'upgrade';
1585    if (EventEmitter.listenerCount(req, eventName) > 0) {
1586      req.upgradeOrConnect = true;
1587
1588      // detach the socket
1589      socket.emit('agentRemove');
1590      socket.removeListener('close', socketCloseListener);
1591      socket.removeListener('error', socketErrorListener);
1592
1593      req.emit(eventName, res, socket, bodyHead);
1594      req.emit('close');
1595    } else {
1596      // Got Upgrade header or CONNECT method, but have no handler.
1597      socket.destroy();
1598    }
1599    freeParser(parser, req);
1600  } else if (parser.incoming && parser.incoming.complete &&
1601             // When the status code is 100 (Continue), the server will
1602             // send a final response after this client sends a request
1603             // body. So, we must not free the parser.
1604             parser.incoming.statusCode !== 100) {
1605    freeParser(parser, req);
1606  }
1607}
1608
1609
1610// client
1611function parserOnIncomingClient(res, shouldKeepAlive) {
1612  var parser = this;
1613  var socket = this.socket;
1614  var req = socket._httpMessage;
1615
1616
1617  // propogate "domain" setting...
1618  if (req.domain && !res.domain) {
1619    debug('setting "res.domain"');
1620    res.domain = req.domain;
1621  }
1622
1623  debug('AGENT incoming response!');
1624
1625  if (req.res) {
1626    // We already have a response object, this means the server
1627    // sent a double response.
1628    socket.destroy();
1629    return;
1630  }
1631  req.res = res;
1632
1633  // Responses to CONNECT request is handled as Upgrade.
1634  if (req.method === 'CONNECT') {
1635    res.upgrade = true;
1636    return true; // skip body
1637  }
1638
1639  // Responses to HEAD requests are crazy.
1640  // HEAD responses aren't allowed to have an entity-body
1641  // but *can* have a content-length which actually corresponds
1642  // to the content-length of the entity-body had the request
1643  // been a GET.
1644  var isHeadResponse = req.method == 'HEAD';
1645  debug('AGENT isHeadResponse ' + isHeadResponse);
1646
1647  if (res.statusCode == 100) {
1648    // restart the parser, as this is a continue message.
1649    delete req.res; // Clear res so that we don't hit double-responses.
1650    req.emit('continue');
1651    return true;
1652  }
1653
1654  if (req.shouldKeepAlive && !shouldKeepAlive && !req.upgradeOrConnect) {
1655    // Server MUST respond with Connection:keep-alive for us to enable it.
1656    // If we've been upgraded (via WebSockets) we also shouldn't try to
1657    // keep the connection open.
1658    req.shouldKeepAlive = false;
1659  }
1660
1661
1662  DTRACE_HTTP_CLIENT_RESPONSE(socket, req);
1663  COUNTER_HTTP_CLIENT_RESPONSE();
1664  req.res = res;
1665  res.req = req;
1666
1667  // add our listener first, so that we guarantee socket cleanup
1668  res.on('end', responseOnEnd);
1669  var handled = req.emit('response', res);
1670
1671  // If the user did not listen for the 'response' event, then they
1672  // can't possibly read the data, so we ._dump() it into the void
1673  // so that the socket doesn't hang there in a paused state.
1674  if (!handled)
1675    res._dump();
1676
1677  return isHeadResponse;
1678}
1679
1680// client
1681function responseOnEnd() {
1682  var res = this;
1683  var req = res.req;
1684  var socket = req.socket;
1685
1686  if (!req.shouldKeepAlive) {
1687    if (socket.writable) {
1688      debug('AGENT socket.destroySoon()');
1689      socket.destroySoon();
1690    }
1691    assert(!socket.writable);
1692  } else {
1693    debug('AGENT socket keep-alive');
1694    if (req.timeoutCb) {
1695      socket.setTimeout(0, req.timeoutCb);
1696      req.timeoutCb = null;
1697    }
1698    socket.removeListener('close', socketCloseListener);
1699    socket.removeListener('error', socketErrorListener);
1700    // Mark this socket as available, AFTER user-added end
1701    // handlers have a chance to run.
1702    process.nextTick(function() {
1703      socket.emit('free');
1704    });
1705  }
1706}
1707
1708ClientRequest.prototype.onSocket = function(socket) {
1709  var req = this;
1710
1711  process.nextTick(function() {
1712    var parser = parsers.alloc();
1713    req.socket = socket;
1714    req.connection = socket;
1715    parser.reinitialize(HTTPParser.RESPONSE);
1716    parser.socket = socket;
1717    parser.incoming = null;
1718    req.parser = parser;
1719
1720    socket.parser = parser;
1721    socket._httpMessage = req;
1722
1723    // Setup "drain" propogation.
1724    httpSocketSetup(socket);
1725
1726    // Propagate headers limit from request object to parser
1727    if (typeof req.maxHeadersCount === 'number') {
1728      parser.maxHeaderPairs = req.maxHeadersCount << 1;
1729    } else {
1730      // Set default value because parser may be reused from FreeList
1731      parser.maxHeaderPairs = 2000;
1732    }
1733
1734    socket.on('error', socketErrorListener);
1735    socket.ondata = socketOnData;
1736    socket.onend = socketOnEnd;
1737    socket.on('close', socketCloseListener);
1738    parser.onIncoming = parserOnIncomingClient;
1739    req.emit('socket', sock

Large files files are truncated, but you can click here to view the full file