PageRenderTime 84ms CodeModel.GetById 2ms app.highlight 68ms RepoModel.GetById 2ms app.codeStats 0ms

/node-v0.8.11/lib/http.js

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

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