The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / lib / http.js @ b0c0111b

History | View | Annotate | Download (49 KB)

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

    
22
var util = require('util');
23
var net = require('net');
24
var Stream = require('stream');
25
var url = require('url');
26
var EventEmitter = require('events').EventEmitter;
27
var FreeList = require('freelist').FreeList;
28
var HTTPParser = process.binding('http_parser').HTTPParser;
29
var assert = require('assert').ok;
30
var END_OF_FILE = {};
31

    
32

    
33
var debug;
34
if (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.
45
function 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.
59
function 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

    
117
function 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

    
127
function 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

    
160
var 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
});
178
exports.parsers = parsers;
179

    
180

    
181
var CRLF = '\r\n';
182
var 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

    
242
var connectionExpression = /Connection/i;
243
var transferEncodingExpression = /Transfer-Encoding/i;
244
var closeExpression = /close/i;
245
var chunkExpression = /chunk/i;
246
var contentLengthExpression = /Content-Length/i;
247
var dateExpression = /Date/i;
248
var expectExpression = /Expect/i;
249
var continueExpression = /100-continue/i;
250

    
251
var dateCache;
252
function 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. */
265
function 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
}
293
util.inherits(IncomingMessage, Stream);
294

    
295

    
296
exports.IncomingMessage = IncomingMessage;
297

    
298

    
299
IncomingMessage.prototype.destroy = function(error) {
300
  this.socket.destroy(error);
301
};
302

    
303

    
304
IncomingMessage.prototype.setEncoding = function(encoding) {
305
  var StringDecoder = require('string_decoder').StringDecoder; // lazy load
306
  this._decoder = new StringDecoder(encoding);
307
};
308

    
309

    
310
IncomingMessage.prototype.pause = function() {
311
  this._paused = true;
312
  this.socket.pause();
313
};
314

    
315

    
316
IncomingMessage.prototype.resume = function() {
317
  this._paused = false;
318
  if (this.socket) {
319
    this.socket.resume();
320
  }
321

    
322
  this._emitPending();
323
};
324

    
325

    
326
IncomingMessage.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

    
352
IncomingMessage.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

    
364
IncomingMessage.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.
380
IncomingMessage.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

    
431
function 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
}
450
util.inherits(OutgoingMessage, Stream);
451

    
452

    
453
exports.OutgoingMessage = OutgoingMessage;
454

    
455

    
456
OutgoingMessage.prototype.destroy = function(error) {
457
  this.socket.destroy(error);
458
};
459

    
460

    
461
// This abstract either writing directly to the socket or buffering it.
462
OutgoingMessage.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

    
479
OutgoingMessage.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

    
507
OutgoingMessage.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

    
534
OutgoingMessage.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

    
638
OutgoingMessage.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

    
655
OutgoingMessage.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

    
667
OutgoingMessage.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

    
684
OutgoingMessage.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

    
702
OutgoingMessage.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

    
741
OutgoingMessage.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

    
761
OutgoingMessage.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

    
828
OutgoingMessage.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

    
840
OutgoingMessage.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

    
886
function 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
}
898
util.inherits(ServerResponse, OutgoingMessage);
899

    
900

    
901
exports.ServerResponse = ServerResponse;
902

    
903
ServerResponse.prototype.statusCode = 200;
904

    
905
function onServerResponseClose() {
906
  this._httpMessage.emit('close');
907
}
908

    
909
ServerResponse.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

    
918
ServerResponse.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

    
925
ServerResponse.prototype.writeContinue = function() {
926
  this._writeRaw('HTTP/1.1 100 Continue' + CRLF + CRLF, 'ascii');
927
  this._sent100 = true;
928
};
929

    
930
ServerResponse.prototype._implicitHeader = function() {
931
  this.writeHead(this.statusCode);
932
};
933

    
934
ServerResponse.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

    
1007
ServerResponse.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

    
1024
function 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
}
1054
util.inherits(Agent, EventEmitter);
1055
exports.Agent = Agent;
1056

    
1057
Agent.defaultMaxSockets = 5;
1058

    
1059
Agent.prototype.defaultPort = 80;
1060
Agent.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
};
1079
Agent.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
};
1122
Agent.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

    
1140
var globalAgent = new Agent();
1141
exports.globalAgent = globalAgent;
1142

    
1143

    
1144
function 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
}
1240
util.inherits(ClientRequest, OutgoingMessage);
1241

    
1242
exports.ClientRequest = ClientRequest;
1243

    
1244
ClientRequest.prototype._implicitHeader = function() {
1245
  this._storeHeader(this.method + ' ' + this.path + ' HTTP/1.1\r\n',
1246
                    this._renderHeaders());
1247
};
1248

    
1249
ClientRequest.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

    
1262
function 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.
1275
function 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

    
1295
function 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

    
1323
function 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

    
1343
function 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

    
1361
function 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

    
1410
function parserOnIncomingClient(res, shouldKeepAlive) {
1411
  var parser = this;
1412
  var socket = this.socket;
1413
  var req = socket._httpMessage;
1414

    
1415
  debug('AGENT incoming response!');
1416

    
1417
  if (req.res) {
1418
    // We already have a response object, this means the server
1419
    // sent a double response.
1420
    socket.destroy();
1421
    return;
1422
  }
1423
  req.res = res;
1424

    
1425
  // Responses to CONNECT request is handled as Upgrade.
1426
  if (req.method === 'CONNECT') {
1427
    res.upgrade = true;
1428
    return true; // skip body
1429
  }
1430

    
1431
  // Responses to HEAD requests are crazy.
1432
  // HEAD responses aren't allowed to have an entity-body
1433
  // but *can* have a content-length which actually corresponds
1434
  // to the content-length of the entity-body had the request
1435
  // been a GET.
1436
  var isHeadResponse = req.method == 'HEAD';
1437
  debug('AGENT isHeadResponse ' + isHeadResponse);
1438

    
1439
  if (res.statusCode == 100) {
1440
    // restart the parser, as this is a continue message.
1441
    delete req.res; // Clear res so that we don't hit double-responses.
1442
    req.emit('continue');
1443
    return true;
1444
  }
1445

    
1446
  if (req.shouldKeepAlive && !shouldKeepAlive && !req.upgradeOrConnect) {
1447
    // Server MUST respond with Connection:keep-alive for us to enable it.
1448
    // If we've been upgraded (via WebSockets) we also shouldn't try to
1449
    // keep the connection open.
1450
    req.shouldKeepAlive = false;
1451
  }
1452

    
1453

    
1454
  DTRACE_HTTP_CLIENT_RESPONSE(socket, req);
1455
  req.emit('response', res);
1456
  req.res = res;
1457
  res.req = req;
1458

    
1459
  res.on('end', responseOnEnd);
1460

    
1461
  return isHeadResponse;
1462
}
1463

    
1464
function responseOnEnd() {
1465
  var res = this;
1466
  var req = res.req;
1467
  var socket = req.socket;
1468

    
1469
  if (!req.shouldKeepAlive) {
1470
    if (socket.writable) {
1471
      debug('AGENT socket.destroySoon()');
1472
      socket.destroySoon();
1473
    }
1474
    assert(!socket.writable);
1475
  } else {
1476
    debug('AGENT socket keep-alive');
1477
    socket.removeListener('close', socketCloseListener);
1478
    socket.removeListener('error', socketErrorListener);
1479
    socket.emit('free');
1480
  }
1481
}
1482

    
1483
ClientRequest.prototype.onSocket = function(socket) {
1484
  var req = this;
1485

    
1486
  process.nextTick(function() {
1487
    var parser = parsers.alloc();
1488
    req.socket = socket;
1489
    req.connection = socket;
1490
    parser.reinitialize(HTTPParser.RESPONSE);
1491
    parser.socket = socket;
1492
    parser.incoming = null;
1493
    req.parser = parser;
1494

    
1495
    socket.parser = parser;
1496
    socket._httpMessage = req;
1497

    
1498
    // Setup "drain" propogation.
1499
    httpSocketSetup(socket);
1500

    
1501
    // Propagate headers limit from request object to parser
1502
    if (typeof req.maxHeadersCount === 'number') {
1503
      parser.maxHeaderPairs = req.maxHeadersCount << 1;
1504
    } else {
1505
      // Set default value because parser may be reused from FreeList
1506
      parser.maxHeaderPairs = 2000;
1507
    }
1508

    
1509
    socket.on('error', socketErrorListener);
1510
    socket.ondata = socketOnData;
1511
    socket.onend = socketOnEnd;
1512
    socket.on('close', socketCloseListener);
1513
    parser.onIncoming = parserOnIncomingClient;
1514
    req.emit('socket', socket);
1515
  });
1516

    
1517
};
1518

    
1519
ClientRequest.prototype._deferToConnect = function(method, arguments_, cb) {
1520
  // This function is for calls that need to happen once the socket is
1521
  // connected and writable. It's an important promisy thing for all the socket
1522
  // calls that happen either now (when a socket is assigned) or
1523
  // in the future (when a socket gets assigned out of the pool and is
1524
  // eventually writable).
1525
  var self = this;
1526
  var onSocket = function() {
1527
    if (self.socket.writable) {
1528
      if (method) {
1529
        self.socket[method].apply(self.socket, arguments_);
1530
      }
1531
      if (cb) { cb(); }
1532
    } else {
1533
      self.socket.once('connect', function() {
1534
        if (method) {
1535
          self.socket[method].apply(self.socket, arguments_);
1536
        }
1537
        if (cb) { cb(); }
1538
      });
1539
    }
1540
  }
1541
  if (!self.socket) {
1542
    self.once('socket', onSocket);
1543
  } else {
1544
    onSocket();
1545
  }
1546
};
1547

    
1548
ClientRequest.prototype.setTimeout = function(msecs, callback) {
1549
  if (callback) this.once('timeout', callback);
1550

    
1551
  var self = this;
1552
  function emitTimeout() {
1553
    self.emit('timeout');
1554
  }
1555

    
1556
  if (this.socket && this.socket.writable) {
1557
    this.socket.setTimeout(msecs, emitTimeout);
1558
    return;
1559
  }
1560

    
1561
  if (this.socket) {
1562
    this.socket.once('connect', function() {
1563
      this.setTimeout(msecs, emitTimeout);
1564
    });
1565
    return;
1566
  }
1567

    
1568
  this.once('socket', function(sock) {
1569
    this.setTimeout(msecs, emitTimeout);
1570
  });
1571
};
1572

    
1573
ClientRequest.prototype.setNoDelay = function() {
1574
  this._deferToConnect('setNoDelay', arguments);
1575
};
1576
ClientRequest.prototype.setSocketKeepAlive = function() {
1577
  this._deferToConnect('setKeepAlive', arguments);
1578
};
1579

    
1580
ClientRequest.prototype.clearTimeout = function(cb) {
1581
  this.setTimeout(0, cb);
1582
};
1583

    
1584
exports.request = function(options, cb) {
1585
  if (typeof options === 'string') {
1586
    options = url.parse(options);
1587
  }
1588

    
1589
  if (options.protocol && options.protocol !== 'http:') {
1590
    throw new Error('Protocol:' + options.protocol + ' not supported.');
1591
  }
1592

    
1593
  return new ClientRequest(options, cb);
1594
};
1595

    
1596
exports.get = function(options, cb) {
1597
  var req = exports.request(options, cb);
1598
  req.end();
1599
  return req;
1600
};
1601

    
1602

    
1603
function ondrain() {
1604
  if (this._httpMessage) this._httpMessage.emit('drain');
1605
}
1606

    
1607

    
1608
function httpSocketSetup(socket) {
1609
  socket.removeListener('drain', ondrain);
1610
  socket.on('drain', ondrain);
1611
}
1612

    
1613

    
1614
function Server(requestListener) {
1615
  if (!(this instanceof Server)) return new Server(requestListener);
1616
  net.Server.call(this, { allowHalfOpen: true });
1617

    
1618
  if (requestListener) {
1619
    this.addListener('request', requestListener);
1620
  }
1621

    
1622
  // Similar option to this. Too lazy to write my own docs.
1623
  // http://www.squid-cache.org/Doc/config/half_closed_clients/
1624
  // http://wiki.squid-cache.org/SquidFaq/InnerWorkings#What_is_a_half-closed_filedescriptor.3F
1625
  this.httpAllowHalfOpen = false;
1626

    
1627
  this.addListener('connection', connectionListener);
1628
}
1629
util.inherits(Server, net.Server);
1630

    
1631

    
1632
exports.Server = Server;
1633

    
1634

    
1635
exports.createServer = function(requestListener) {
1636
  return new Server(requestListener);
1637
};
1638

    
1639

    
1640
function connectionListener(socket) {
1641
  var self = this;
1642
  var outgoing = [];
1643
  var incoming = [];
1644

    
1645
  function abortIncoming() {
1646
    while (incoming.length) {
1647
      var req = incoming.shift();
1648
      req.emit('aborted');
1649
      req.emit('close');
1650
    }
1651
    // abort socket._httpMessage ?
1652
  }
1653

    
1654
  function serverSocketCloseListener() {
1655
    debug('server socket close');
1656
    // mark this parser as reusable
1657
    freeParser(parser);
1658

    
1659
    abortIncoming();
1660
  }
1661

    
1662
  debug('SERVER new http connection');
1663

    
1664
  httpSocketSetup(socket);
1665

    
1666
  socket.setTimeout(2 * 60 * 1000); // 2 minute timeout
1667
  socket.once('timeout', function() {
1668
    socket.destroy();
1669
  });
1670

    
1671
  var parser = parsers.alloc();
1672
  parser.reinitialize(HTTPParser.REQUEST);
1673
  parser.socket = socket;
1674
  socket.parser = parser;
1675
  parser.incoming = null;
1676

    
1677
  // Propagate headers limit from server instance to parser
1678
  if (typeof this.maxHeadersCount === 'number') {
1679
    parser.maxHeaderPairs = this.maxHeadersCount << 1;
1680
  } else {
1681
    // Set default value because parser may be reused from FreeList
1682
    parser.maxHeaderPairs = 2000;
1683
  }
1684

    
1685
  socket.addListener('error', function(e) {
1686
    self.emit('clientError', e);
1687
  });
1688

    
1689
  socket.ondata = function(d, start, end) {
1690
    var ret = parser.execute(d, start, end - start);
1691
    if (ret instanceof Error) {
1692
      debug('parse error');
1693
      socket.destroy(ret);
1694
    } else if (parser.incoming && parser.incoming.upgrade) {
1695
      // Upgrade or CONNECT
1696
      var bytesParsed = ret;
1697
      var req = parser.incoming;
1698

    
1699
      socket.ondata = null;
1700
      socket.onend = null;
1701
      socket.removeListener('close', serverSocketCloseListener);
1702
      parser.finish();
1703
      freeParser(parser, req);
1704

    
1705
      // This is start + byteParsed
1706
      var bodyHead = d.slice(start + bytesParsed, end);
1707

    
1708
      var eventName = req.method === 'CONNECT' ? 'connect' : 'upgrade';
1709
      if (self.listeners(eventName).length) {
1710
        self.emit(eventName, req, req.socket, bodyHead);
1711
      } else {
1712
        // Got upgrade header or CONNECT method, but have no handler.
1713
        socket.destroy();
1714
      }
1715
    }
1716
  };
1717

    
1718
  socket.onend = function() {
1719
    var ret = parser.finish();
1720

    
1721
    if (ret instanceof Error) {
1722
      debug('parse error');
1723
      socket.destroy(ret);
1724
      return;
1725
    }
1726

    
1727
    if (!self.httpAllowHalfOpen) {
1728
      abortIncoming();
1729
      if (socket.writable) socket.end();
1730
    } else if (outgoing.length) {
1731
      outgoing[outgoing.length - 1]._last = true;
1732
    } else if (socket._httpMessage) {
1733
      socket._httpMessage._last = true;
1734
    } else {
1735
      if (socket.writable) socket.end();
1736
    }
1737
  };
1738

    
1739
  socket.addListener('close', serverSocketCloseListener);
1740

    
1741
  // The following callback is issued after the headers have been read on a
1742
  // new message. In this callback we setup the response object and pass it
1743
  // to the user.
1744
  parser.onIncoming = function(req, shouldKeepAlive) {
1745
    incoming.push(req);
1746

    
1747
    var res = new ServerResponse(req);
1748
    debug('server response shouldKeepAlive: ' + shouldKeepAlive);
1749
    res.shouldKeepAlive = shouldKeepAlive;
1750
    DTRACE_HTTP_SERVER_REQUEST(req, socket);
1751

    
1752
    if (socket._httpMessage) {
1753
      // There are already pending outgoing res, append.
1754
      outgoing.push(res);
1755
    } else {
1756
      res.assignSocket(socket);
1757
    }
1758

    
1759
    // When we're finished writing the response, check if this is the last
1760
    // respose, if so destroy the socket.
1761
    res.on('finish', function() {
1762
      // Usually the first incoming element should be our request.  it may
1763
      // be that in the case abortIncoming() was called that the incoming
1764
      // array will be empty.
1765
      assert(incoming.length == 0 || incoming[0] === req);
1766

    
1767
      incoming.shift();
1768

    
1769
      res.detachSocket(socket);
1770

    
1771
      if (res._last) {
1772
        socket.destroySoon();
1773
      } else {
1774
        // start sending the next message
1775
        var m = outgoing.shift();
1776
        if (m) {
1777
          m.assignSocket(socket);
1778
        }
1779
      }
1780
    });
1781

    
1782
    if ('expect' in req.headers &&
1783
        (req.httpVersionMajor == 1 && req.httpVersionMinor == 1) &&
1784
        continueExpression.test(req.headers['expect'])) {
1785
      res._expect_continue = true;
1786
      if (self.listeners('checkContinue').length) {
1787
        self.emit('checkContinue', req, res);
1788
      } else {
1789
        res.writeContinue();
1790
        self.emit('request', req, res);
1791
      }
1792
    } else {
1793
      self.emit('request', req, res);
1794
    }
1795
    return false; // Not a HEAD response. (Not even a response!)
1796
  };
1797
}
1798
exports._connectionListener = connectionListener;
1799

    
1800
// Legacy Interface
1801

    
1802
function Client(port, host) {
1803
  if (!(this instanceof Client)) return new Client(port, host);
1804
  EventEmitter.call(this);
1805

    
1806
  host = host || 'localhost';
1807
  port = port || 80;
1808
  this.host = host;
1809
  this.port = port;
1810
  this.agent = new Agent({ host: host, port: port, maxSockets: 1 });
1811
}
1812
util.inherits(Client, EventEmitter);
1813
Client.prototype.request = function(method, path, headers) {
1814
  var self = this;
1815
  var options = {};
1816
  options.host = self.host;
1817
  options.port = self.port;
1818
  if (method[0] === '/') {
1819
    headers = path;
1820
    path = method;
1821
    method = 'GET';
1822
  }
1823
  options.method = method;
1824
  options.path = path;
1825
  options.headers = headers;
1826
  options.agent = self.agent;
1827
  var c = new ClientRequest(options);
1828
  c.on('error', function(e) {
1829
    self.emit('error', e);
1830
  });
1831
  // The old Client interface emitted 'end' on socket end.
1832
  // This doesn't map to how we want things to operate in the future
1833
  // but it will get removed when we remove this legacy interface.
1834
  c.on('socket', function(s) {
1835
    s.on('end', function() {
1836
      self.emit('end');
1837
    });
1838
  });
1839
  return c;
1840
};
1841

    
1842
exports.Client = util.deprecate(Client,
1843
    'http.Client will be removed soon. Do not use it.');
1844

    
1845
exports.createClient = util.deprecate(function(port, host) {
1846
  return new Client(port, host);
1847
}, 'http.createClient is deprecated. Use `http.request` instead.');