PageRenderTime 118ms CodeModel.GetById 13ms app.highlight 91ms RepoModel.GetById 1ms app.codeStats 1ms

/samples/JavaScript/http.js

https://github.com/Dev-Dipesh/linguist
JavaScript | 1838 lines | 1313 code | 305 blank | 220 comment | 311 complexity | b06baa1f4a48b352b642ca5e76fee0ed 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.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.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.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.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    console.error('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    console.error('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 = false;
 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  var self = this;
1026  self.options = options || {};
1027  self.requests = {};
1028  self.sockets = {};
1029  self.maxSockets = self.options.maxSockets || Agent.defaultMaxSockets;
1030  self.on('free', function(socket, host, port, localAddress) {
1031    var name = host + ':' + port;
1032    if (localAddress) {
1033      name += ':' + localAddress;
1034    }
1035
1036    if (self.requests[name] && self.requests[name].length) {
1037      self.requests[name].shift().onSocket(socket);
1038      if (self.requests[name].length === 0) {
1039        // don't leak
1040        delete self.requests[name];
1041      }
1042    } else {
1043      // If there are no pending requests just destroy the
1044      // socket and it will get removed from the pool. This
1045      // gets us out of timeout issues and allows us to
1046      // default to Connection:keep-alive.
1047      socket.destroy();
1048    }
1049  });
1050  self.createConnection = net.createConnection;
1051}
1052util.inherits(Agent, EventEmitter);
1053exports.Agent = Agent;
1054
1055Agent.defaultMaxSockets = 5;
1056
1057Agent.prototype.defaultPort = 80;
1058Agent.prototype.addRequest = function(req, host, port, localAddress) {
1059  var name = host + ':' + port;
1060  if (localAddress) {
1061    name += ':' + localAddress;
1062  }
1063  if (!this.sockets[name]) {
1064    this.sockets[name] = [];
1065  }
1066  if (this.sockets[name].length < this.maxSockets) {
1067    // If we are under maxSockets create a new one.
1068    req.onSocket(this.createSocket(name, host, port, localAddress));
1069  } else {
1070    // We are over limit so we'll add it to the queue.
1071    if (!this.requests[name]) {
1072      this.requests[name] = [];
1073    }
1074    this.requests[name].push(req);
1075  }
1076};
1077Agent.prototype.createSocket = function(name, host, port, localAddress) {
1078  var self = this;
1079  var options = util._extend({}, self.options);
1080  options.port = port;
1081  options.host = host;
1082  options.localAddress = localAddress;
1083  var s = self.createConnection(options);
1084  if (!self.sockets[name]) {
1085    self.sockets[name] = [];
1086  }
1087  this.sockets[name].push(s);
1088  var onFree = function() {
1089    self.emit('free', s, host, port, localAddress);
1090  }
1091  s.on('free', onFree);
1092  var onClose = function(err) {
1093    // This is the only place where sockets get removed from the Agent.
1094    // If you want to remove a socket from the pool, just close it.
1095    // All socket errors end in a close event anyway.
1096    self.removeSocket(s, name, host, port, localAddress);
1097  }
1098  s.on('close', onClose);
1099  var onRemove = function() {
1100    // We need this function for cases like HTTP 'upgrade'
1101    // (defined by WebSockets) where we need to remove a socket from the pool
1102    //  because it'll be locked up indefinitely
1103    self.removeSocket(s, name, host, port, localAddress);
1104    s.removeListener('close', onClose);
1105    s.removeListener('free', onFree);
1106    s.removeListener('agentRemove', onRemove);
1107  }
1108  s.on('agentRemove', onRemove);
1109  return s;
1110};
1111Agent.prototype.removeSocket = function(s, name, host, port, localAddress) {
1112  if (this.sockets[name]) {
1113    var index = this.sockets[name].indexOf(s);
1114    if (index !== -1) {
1115      this.sockets[name].splice(index, 1);
1116      if (this.sockets[name].length === 0) {
1117        // don't leak
1118        delete this.sockets[name];
1119      }
1120    }
1121  }
1122  if (this.requests[name] && this.requests[name].length) {
1123    // If we have pending requests and a socket gets closed a new one
1124    this.createSocket(name, host, port, localAddress).emit('free');
1125  }
1126};
1127
1128var globalAgent = new Agent();
1129exports.globalAgent = globalAgent;
1130
1131
1132function ClientRequest(options, cb) {
1133  var self = this;
1134  OutgoingMessage.call(self);
1135
1136  self.agent = options.agent === undefined ? globalAgent : options.agent;
1137
1138  var defaultPort = options.defaultPort || 80;
1139
1140  var port = options.port || defaultPort;
1141  var host = options.hostname || options.host || 'localhost';
1142
1143  if (options.setHost === undefined) {
1144    var setHost = true;
1145  }
1146
1147  self.socketPath = options.socketPath;
1148
1149  var method = self.method = (options.method || 'GET').toUpperCase();
1150  self.path = options.path || '/';
1151  if (cb) {
1152    self.once('response', cb);
1153  }
1154
1155  if (!Array.isArray(options.headers)) {
1156    if (options.headers) {
1157      var keys = Object.keys(options.headers);
1158      for (var i = 0, l = keys.length; i < l; i++) {
1159        var key = keys[i];
1160        self.setHeader(key, options.headers[key]);
1161      }
1162    }
1163    if (host && !this.getHeader('host') && setHost) {
1164      var hostHeader = host;
1165      if (port && +port !== defaultPort) {
1166        hostHeader += ':' + port;
1167      }
1168      this.setHeader('Host', hostHeader);
1169    }
1170  }
1171
1172  if (options.auth && !this.getHeader('Authorization')) {
1173    //basic auth
1174    this.setHeader('Authorization', 'Basic ' +
1175                   new Buffer(options.auth).toString('base64'));
1176  }
1177
1178  if (method === 'GET' || method === 'HEAD' || method === 'CONNECT') {
1179    self.useChunkedEncodingByDefault = false;
1180  } else {
1181    self.useChunkedEncodingByDefault = true;
1182  }
1183
1184  if (Array.isArray(options.headers)) {
1185    self._storeHeader(self.method + ' ' + self.path + ' HTTP/1.1\r\n',
1186                      options.headers);
1187  } else if (self.getHeader('expect')) {
1188    self._storeHeader(self.method + ' ' + self.path + ' HTTP/1.1\r\n',
1189                      self._renderHeaders());
1190  }
1191  if (self.socketPath) {
1192    self._last = true;
1193    self.shouldKeepAlive = false;
1194    if (options.createConnection) {
1195      self.onSocket(options.createConnection(self.socketPath));
1196    } else {
1197      self.onSocket(net.createConnection(self.socketPath));
1198    }
1199  } else if (self.agent) {
1200    // If there is an agent we should default to Connection:keep-alive.
1201    self._last = false;
1202    self.shouldKeepAlive = true;
1203    self.agent.addRequest(self, host, port, options.localAddress);
1204  } else {
1205    // No agent, default to Connection:close.
1206    self._last = true;
1207    self.shouldKeepAlive = false;
1208    if (options.createConnection) {
1209      options.port = port;
1210      options.host = host;
1211      var conn = options.createConnection(options);
1212    } else {
1213      var conn = net.createConnection({
1214        port: port,
1215        host: host,
1216        localAddress: options.localAddress
1217      });
1218    }
1219    self.onSocket(conn);
1220  }
1221
1222  self._deferToConnect(null, null, function() {
1223    self._flush();
1224    self = null;
1225  });
1226
1227}
1228util.inherits(ClientRequest, OutgoingMessage);
1229
1230exports.ClientRequest = ClientRequest;
1231
1232ClientRequest.prototype._implicitHeader = function() {
1233  this._storeHeader(this.method + ' ' + this.path + ' HTTP/1.1\r\n',
1234                    this._renderHeaders());
1235};
1236
1237ClientRequest.prototype.abort = function() {
1238  if (this.socket) {
1239    // in-progress
1240    this.socket.destroy();
1241  } else {
1242    // haven't been assigned a socket yet.
1243    // this could be more efficient, it could
1244    // remove itself from the pending requests
1245    this._deferToConnect('destroy', []);
1246  }
1247};
1248
1249
1250function createHangUpError() {
1251  var error = new Error('socket hang up');
1252  error.code = 'ECONNRESET';
1253  return error;
1254}
1255
1256// Free the parser and also break any links that it
1257// might have to any other things.
1258// TODO: All parser data should be attached to a
1259// single object, so that it can be easily cleaned
1260// up by doing `parser.data = {}`, which should
1261// be done in FreeList.free.  `parsers.free(parser)`
1262// should be all that is needed.
1263function freeParser(parser, req) {
1264  if (parser) {
1265    parser._headers = [];
1266    parser.onIncoming = null;
1267    if (parser.socket) {
1268      parser.socket.onend = null;
1269      parser.socket.ondata = null;
1270      parser.socket.parser = null;
1271    }
1272    parser.socket = null;
1273    parser.incoming = null;
1274    parsers.free(parser);
1275    parser = null;
1276  }
1277  if (req) {
1278    req.parser = null;
1279  }
1280}
1281
1282
1283function socketCloseListener() {
1284  var socket = this;
1285  var parser = socket.parser;
1286  var req = socket._httpMessage;
1287  debug('HTTP socket close');
1288  req.emit('close');
1289  if (req.res && req.res.readable) {
1290    // Socket closed before we emitted 'end' below.
1291    req.res.emit('aborted');
1292    var res = req.res;
1293    req.res._emitPending(function() {
1294      res._emitEnd();
1295      res.emit('close');
1296      res = null;
1297    });
1298  } else if (!req.res && !req._hadError) {
1299    // This socket error fired before we started to
1300    // receive a response. The error needs to
1301    // fire on the request.
1302    req.emit('error', createHangUpError());
1303  }
1304
1305  if (parser) {
1306    parser.finish();
1307    freeParser(parser, req);
1308  }
1309}
1310
1311function socketErrorListener(err) {
1312  var socket = this;
1313  var parser = socket.parser;
1314  var req = socket._httpMessage;
1315  debug('HTTP SOCKET ERROR: ' + err.message + '\n' + err.stack);
1316
1317  if (req) {
1318    req.emit('error', err);
1319    // For Safety. Some additional errors might fire later on
1320    // and we need to make sure we don't double-fire the error event.
1321    req._hadError = true;
1322  }
1323
1324  if (parser) {
1325    parser.finish();
1326    freeParser(parser, req);
1327  }
1328  socket.destroy();
1329}
1330
1331function socketOnEnd() {
1332  var socket = this;
1333  var req = this._httpMessage;
1334  var parser = this.parser;
1335
1336  if (!req.res) {
1337    // If we don't have a response then we know that the socket
1338    // ended prematurely and we need to emit an error on the request.
1339    req.emit('error', createHangUpError());
1340    req._hadError = true;
1341  }
1342  if (parser) {
1343    parser.finish();
1344    freeParser(parser, req);
1345  }
1346  socket.destroy();
1347}
1348
1349function socketOnData(d, start, end) {
1350  var socket = this;
1351  var req = this._httpMessage;
1352  var parser = this.parser;
1353
1354  var ret = parser.execute(d, start, end - start);
1355  if (ret instanceof Error) {
1356    debug('parse error');
1357    freeParser(parser, req);
1358    socket.destroy(ret);
1359  } else if (parser.incoming && parser.incoming.upgrade) {
1360    // Upgrade or CONNECT
1361    var bytesParsed = ret;
1362    var res = parser.incoming;
1363    req.res = res;
1364
1365    socket.ondata = null;
1366    socket.onend = null;
1367    parser.finish();
1368
1369    // This is start + byteParsed
1370    var bodyHead = d.slice(start + bytesParsed, end);
1371
1372    var eventName = req.method === 'CONNECT' ? 'connect' : 'upgrade';
1373    if (req.listeners(eventName).length) {
1374      req.upgradeOrConnect = true;
1375
1376      // detach the socket
1377      socket.emit('agentRemove');
1378      socket.removeListener('close', socketCloseListener);
1379      socket.removeListener('error', socketErrorListener);
1380
1381      req.emit(eventName, res, socket, bodyHead);
1382      req.emit('close');
1383    } else {
1384      // Got Upgrade header or CONNECT method, but have no handler.
1385      socket.destroy();
1386    }
1387    freeParser(parser, req);
1388  } else if (parser.incoming && parser.incoming.complete &&
1389             // When the status code is 100 (Continue), the server will
1390             // send a final response after this client sends a request
1391             // body. So, we must not free the parser.
1392             parser.incoming.statusCode !== 100) {
1393    freeParser(parser, req);
1394  }
1395}
1396
1397
1398function parserOnIncomingClient(res, shouldKeepAlive) {
1399  var parser = this;
1400  var socket = this.socket;
1401  var req = socket._httpMessage;
1402
1403  debug('AGENT incoming response!');
1404
1405  if (req.res) {
1406    // We already have a response object, this means the server
1407    // sent a double response.
1408    socket.destroy();
1409    return;
1410  }
1411  req.res = res;
1412
1413  // Responses to CONNECT request is handled as Upgrade.
1414  if (req.method === 'CONNECT') {
1415    res.upgrade = true;
1416    return true; // skip body
1417  }
1418
1419  // Responses to HEAD requests are crazy.
1420  // HEAD responses aren't allowed to have an entity-body
1421  // but *can* have a content-length which actually corresponds
1422  // to the content-length of the entity-body had the request
1423  // been a GET.
1424  var isHeadResponse = req.method == 'HEAD';
1425  debug('AGENT isHeadResponse ' + isHeadResponse);
1426
1427  if (res.statusCode == 100) {
1428    // restart the parser, as this is a continue message.
1429    delete req.res; // Clear res so that we don't hit double-responses.
1430    req.emit('continue');
1431    return true;
1432  }
1433
1434  if (req.shouldKeepAlive && !shouldKeepAlive && !req.upgradeOrConnect) {
1435    // Server MUST respond with Connection:keep-alive for us to enable it.
1436    // If we've been upgraded (via WebSockets) we also shouldn't try to
1437    // keep the connection open.
1438    req.shouldKeepAlive = false;
1439  }
1440
1441
1442  DTRACE_HTTP_CLIENT_RESPONSE(socket, req);
1443  req.emit('response', res);
1444  req.res = res;
1445  res.req = req;
1446
1447  res.on('end', responseOnEnd);
1448
1449  return isHeadResponse;
1450}
1451
1452function responseOnEnd() {
1453  var res = this;
1454  var req = res.req;
1455  var socket = req.socket;
1456
1457  if (!req.shouldKeepAlive) {
1458    if (socket.writable) {
1459      debug('AGENT socket.destroySoon()');
1460      socket.destroySoon();
1461    }
1462    assert(!socket.writable);
1463  } else {
1464    debug('AGENT socket keep-alive');
1465    socket.removeListener('close', socketCloseListener);
1466    socket.removeListener('error', socketErrorListener);
1467    socket.emit('free');
1468  }
1469}
1470
1471ClientRequest.prototype.onSocket = function(socket) {
1472  var req = this;
1473
1474  process.nextTick(function() {
1475    var parser = parsers.alloc();
1476    req.socket = socket;
1477    req.connection = socket;
1478    parser.reinitialize(HTTPParser.RESPONSE);
1479    parser.socket = socket;
1480    parser.incoming = null;
1481    req.parser = parser;
1482
1483    parser.socket = socket;
1484    socket.parser = parser;
1485    parser.incoming = null;
1486    socket._httpMessage = req;
1487
1488    // Setup "drain" propogation.
1489    httpSocketSetup(socket);
1490
1491    // Propagate headers limit from request object to parser
1492    if (typeof req.maxHeadersCount === 'number') {
1493      parser.maxHeaderPairs = req.maxHeadersCount << 1;
1494    } else {
1495      // Set default value because parser may be reused from FreeList
1496      parser.maxHeaderPairs = 2000;
1497    }
1498
1499    socket.on('error', socketErrorListener);
1500    socket.ondata = socketOnData;
1501    socket.onend = socketOnEnd;
1502    socket.on('close', socketCloseListener);
1503    parser.onIncoming = parserOnIncomingClient;
1504    req.emit('socket', socket);
1505  });
1506
1507};
1508
1509ClientRequest.prototype._deferToConnect = function(method, arguments_, cb) {
1510  // This function is for calls that need to happen once the socket is
1511  // connected and writable. It's an important promisy thing for all the socket
1512  // calls that happen either now (when a socket is assigned) or
1513  // in the future (when a socket gets assigned out of the pool and is
1514  // eventually writable).
1515  var self = this;
1516  var onSocket = function() {
1517    if (self.socket.writable) {
1518      if (method) {
1519        self.socket[method].apply(self.socket, arguments_);
1520      }
1521      if (cb) { cb(); }
1522    } else {
1523      self.socket.once('connect', function() {
1524        if (method) {
1525          self.socket[method].apply(self.socket, arguments_);
1526        }
1527        if (cb) { cb(); }
1528      });
1529    }
1530  }
1531  if (!self.socket) {
1532    self.once('socket', onSocket);
1533  } else {
1534    onSocket();
1535  }
1536};
1537
1538ClientRequest.prototype.setTimeout = function(msecs, callback) {
1539  if (callback) this.once('timeout', callback);
1540
1541  var self = this;
1542  function emitTimeout() {
1543    self.emit('timeout');
1544  }
1545
1546  if (this.socket && this.socket.writable) {
1547    this.socket.setTimeout(msecs, emitTimeout);
1548    return;
1549  }
1550
1551  if (this.socket) {
1552    this.socket.once('connect', function() {
1553      this.setTimeout(msecs, emitTimeout);
1554    });
1555    return;
1556  }
1557
1558  this.once('socket', function(sock) {
1559    this.setTimeout(msecs, emitTimeout);
1560  });
1561};
1562
1563ClientRequest.prototype.setNoDelay = function() {
1564  this._deferToConnect('setNoDelay', arguments);
1565};
1566ClientRequest.prototype.setSocketKeepAlive = function() {
1567  this._deferToConnect('setKeepAlive', arguments);
1568};
1569
1570ClientRequest.prototype.clearTimeout = function(cb) {
1571  this.setTimeout(0, cb);
1572};
1573
1574exports.request = function(options, cb) {
1575  if (typeof options === 'string') {
1576    options = url.parse(options);
1577  }
1578
1579  if (options.protocol && options.protocol !== 'http:') {
1580    throw new Error('Protocol:' + options.protocol + ' not supported.');
1581  }
1582
1583  return new ClientRequest(options, cb);
1584};
1585
1586exports.get = function(options, cb) {
1587  var req = exports.request(options, cb);
1588  req.end();
1589  return req;
1590};
1591
1592
1593function ondrain() {
1594  if (this._httpMessage) this._httpMessage.emit('drain');
1595}
1596
1597
1598function httpSocketSetup(socket) {
1599  socket.removeListener('drain', ondrain);
1600  socket.on('drain', ondrain);
1601}
1602
1603
1604function Server(requestListener) {
1605  if (!(this instanceof Server)) return new Server(requestListener);
1606  net.Server.call(this, { allowHalfOpen: true });
1607
1608  if (requestListener) {
1609    this.addListener('request', requestListener);
1610  }
1611
1612  // Similar option to this. Too lazy to write my own docs.
1613  // http://www.squid-cache.org/Doc/config/half_closed_clients/
1614  // http://wiki.squid-cache.org/SquidFaq/InnerWorkings#What_is_a_half-closed_filedescriptor.3F
1615  this.httpAllowHalfOpen = false;
1616
1617  this.addListener('connection', connectionListener);
1618}
1619util.inherits(Server, net.Server);
1620
1621
1622exports.Server = Server;
1623
1624
1625exports.createServer = function(requestListener) {
1626  return new Server(requestListener);
1627};
1628
1629
1630function connectionListener(socket) {
1631  var self = this;
1632  var outgoing = [];
1633  var incoming = [];
1634
1635  function abortIncoming() {
1636    while (incoming.length) {
1637      var req = incoming.shift();
1638      req.emit('aborted');
1639      req.emit('close');
1640    }
1641    // abort socket._httpMessage ?
1642  }
1643
1644  function serverSocketCloseListener() {
1645    debug('server socket close');
1646    // mark this parser as reusable
1647    freeParser(parser);
1648
1649    abortIncoming();
1650  }
1651
1652  debug('SERVER new http connection');
1653
1654  httpSocketSetup(socket);
1655
1656  socket.setTimeout(2 * 60 * 1000); // 2 minute timeout
1657  socket.once('timeout', function() {
1658    socket.destroy();
1659  });
1660
1661  var parser = parsers.alloc();
1662  parser.reinitialize(HTTPParser.REQUEST);
1663  parser.socket = socket;
1664  socket.parser = parser;
1665  parser.incoming = null;
1666
1667  // Propagate headers limit from server instance to parser
1668  if (typeof this.maxHeadersCount === 'number') {
1669    parser.maxHeaderPairs = this.maxHeadersCount << 1;
1670  } else {
1671    // Set default value because parser may be reused from FreeList
1672    parser.maxHeaderPairs = 2000;
1673  }
1674
1675  socket.addListener('error', function(e) {
1676    self.emit('clientError', e);
1677  });
1678
1679  socket.ondata = function(d, start, end) {
1680    var ret = parser.execute(d, start, end - start);
1681    if (ret instanceof Error) {
1682      debug('parse error');
1683      socket.destroy(ret);
1684    } else if (parser.incoming && parser.incoming.upgrade) {
1685      // Upgrade or CONNECT
1686      var bytesParsed = ret;
1687      var req = parser.incoming;
1688
1689      socket.ondata = null;
1690      socket.onend = null;
1691      socket.removeListener('close', serverSocketCloseListener);
1692      parser.finish();
1693      freeParser(parser, req);
1694
1695      // This is start + byteParsed
1696      var bodyHead = d.slice(start + bytesParsed, end);
1697
1698      var eventName = req.method === 'CONNECT' ? 'connect' : 'upgrade';
1699      if (self.listeners(eventName).length) {
1700        self.emit(eventName, req, req.socket, bodyHead);
1701      } else {
1702        // Got upgrade header or CONNECT method, but have no handler.
1703        socket.destroy();
1704      }
1705    }
1706  };
1707
1708  socket.onend = function() {
1709    var ret = parser.finish();
1710
1711    if (ret instanceof Error) {
1712      debug('parse error');
1713      socket.destroy(ret);
1714      return;
1715    }
1716
1717    if (!self.httpAllowHalfOpen) {
1718      abortIncoming();
1719      if (socket.writable) socket.end();
1720    } else if (outgoing.length) {
1721      outgoing[outgoing.length - 1]._last = true;
1722    } else if (socket._httpMessage) {
1723      socket._httpMessage._last = true;
1724    } else {
1725      if (socket.writable) socket.end();
1726    }
1727  };
1728
1729  socket.addListener('close', serverSocketCloseListener);
1730
1731  // The following callback is issued after the headers have been read on a
1732  // new message. In this callback we setup the response object and pass it
1733  // to the user.
1734  parser.onIncoming = function(req, shouldKeepAlive) {
1735    incoming.push(req);
1736
1737    var res = new ServerResponse(req);
1738    debug('server response shouldKeepAlive: ' + shouldKeepAlive);
1739    res.shouldKeepAlive = shouldKeepAlive;
1740    DTRACE_HTTP_SERVER_REQUEST(req, socket);
1741
1742    if (socket._httpMessage) {
1743      // There are already pending outgoing res, append.
1744      outgoing.push(res);
1745    } else {
1746      res.assignSocket(socket);
1747    }
1748
1749    // When we're finished writing the response, check if this is the last
1750    // respose, if so destroy the socket.
1751    res.on('finish', function() {
1752      // Usually the first incoming element should be our request.  it may
1753      // be that in the case abortIncoming() was called that the incoming
1754      // array will be empty.
1755      assert(incoming.length == 0 || incoming[0] === req);
1756
1757      incoming.shift();
1758
1759      res.detachSocket(socket);
1760
1761      if (res._last) {
1762        socket.destroySoon();
1763      } else {
1764        // start sending the next message
1765        var m = outgoing.shift();
1766        if (m) {
1767          m.assignSocket(socket);
1768        }
1769      }
1770    });
1771
1772    if ('expect' in req.headers &&
1773        (req.httpVersionMajor == 1 && req.httpVersionMinor == 1) &&
1774        continueExpression.test(req.headers['expect'])) {
1775      res._expect_continue = true;
1776      if (self.listeners('checkContinue').length) {
1777        self.emit('checkContinue', req, res);
1778      } else {
1779        res.writeContinue();
1780        self.emit('request', req, res);
1781      }
1782    } else {
1783      self.emit('request', req, res);
1784    }
1785    return false; // Not a HEAD response. (Not even a response!)
1786  };
1787}
1788exports._connectionListener = connectionListener;
1789
1790// Legacy Interface
1791
1792function Client(port, host) {
1793  if (!(this instanceof Client)) return new Client(port, host);
1794  host = host || 'localhost';
1795  port = port || 80;
1796  this.host = host;
1797  this.port = port;
1798  this.agent = new Agent({ host: host, port: port, maxSockets: 1 });
1799}
1800util.inherits(Client, EventEmitter);
1801Client.prototype.request = function(method, path, headers) {
1802  var self = this;
1803  var options = {};
1804  options.host = self.host;
1805  options.port = self.port;
1806  if (method[0] === '/') {
1807    headers = path;
1808    path = method;
1809    method = 'GET';
1810  }
1811  options.method = method;
1812  options.path = path;
1813  options.headers = headers;
1814  options.agent = self.agent;
1815  var c = new ClientRequest(options);
1816  c.on('error', function(e) {
1817    self.emit('error', e);
1818  });
1819  // The old Client interface emitted 'end' on socket end.
1820  // This doesn't map to how we want things to operate in the future
1821  // but it will get removed when we remove this legacy interface.
1822  c.on('socket', function(s) {
1823    s.on('end', function() {
1824      self.emit('end');
1825    });
1826  });
1827  return c;
1828};
1829
1830exports.Client = Client;
1831
1832// TODO http.Client can be removed in v0.9. Until then leave this message.
1833module.deprecate('Client', 'It will be removed soon. Do not use it.');
1834
1835exports.createClient = function(port, host) {
1836  return new Cli

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