PageRenderTime 70ms CodeModel.GetById 37ms RepoModel.GetById 0ms app.codeStats 1ms

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

https://bitbucket.org/jmchen/pysource
JavaScript | 1860 lines | 1331 code | 309 blank | 220 comment | 317 complexity | 932d9ce88ff898ff04c86eba9f432da0 MD5 | raw file
Possible License(s): BSD-2-Clause, 0BSD, MIT, WTFPL, BSD-3-Clause, Apache-2.0

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

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