PageRenderTime 64ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/samples/JavaScript/http.js

https://github.com/Dev-Dipesh/linguist
JavaScript | 1838 lines | 1313 code | 305 blank | 220 comment | 311 complexity | b06baa1f4a48b352b642ca5e76fee0ed MD5 | raw file
  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.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.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.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.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. console.error('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. console.error('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 = false;
  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. var self = this;
  838. self.options = options || {};
  839. self.requests = {};
  840. self.sockets = {};
  841. self.maxSockets = self.options.maxSockets || Agent.defaultMaxSockets;
  842. self.on('free', function(socket, host, port, localAddress) {
  843. var name = host + ':' + port;
  844. if (localAddress) {
  845. name += ':' + localAddress;
  846. }
  847. if (self.requests[name] && self.requests[name].length) {
  848. self.requests[name].shift().onSocket(socket);
  849. if (self.requests[name].length === 0) {
  850. // don't leak
  851. delete self.requests[name];
  852. }
  853. } else {
  854. // If there are no pending requests just destroy the
  855. // socket and it will get removed from the pool. This
  856. // gets us out of timeout issues and allows us to
  857. // default to Connection:keep-alive.
  858. socket.destroy();
  859. }
  860. });
  861. self.createConnection = net.createConnection;
  862. }
  863. util.inherits(Agent, EventEmitter);
  864. exports.Agent = Agent;
  865. Agent.defaultMaxSockets = 5;
  866. Agent.prototype.defaultPort = 80;
  867. Agent.prototype.addRequest = function(req, host, port, localAddress) {
  868. var name = host + ':' + port;
  869. if (localAddress) {
  870. name += ':' + localAddress;
  871. }
  872. if (!this.sockets[name]) {
  873. this.sockets[name] = [];
  874. }
  875. if (this.sockets[name].length < this.maxSockets) {
  876. // If we are under maxSockets create a new one.
  877. req.onSocket(this.createSocket(name, host, port, localAddress));
  878. } else {
  879. // We are over limit so we'll add it to the queue.
  880. if (!this.requests[name]) {
  881. this.requests[name] = [];
  882. }
  883. this.requests[name].push(req);
  884. }
  885. };
  886. Agent.prototype.createSocket = function(name, host, port, localAddress) {
  887. var self = this;
  888. var options = util._extend({}, self.options);
  889. options.port = port;
  890. options.host = host;
  891. options.localAddress = localAddress;
  892. var s = self.createConnection(options);
  893. if (!self.sockets[name]) {
  894. self.sockets[name] = [];
  895. }
  896. this.sockets[name].push(s);
  897. var onFree = function() {
  898. self.emit('free', s, host, port, localAddress);
  899. }
  900. s.on('free', onFree);
  901. var onClose = function(err) {
  902. // This is the only place where sockets get removed from the Agent.
  903. // If you want to remove a socket from the pool, just close it.
  904. // All socket errors end in a close event anyway.
  905. self.removeSocket(s, name, host, port, localAddress);
  906. }
  907. s.on('close', onClose);
  908. var onRemove = function() {
  909. // We need this function for cases like HTTP 'upgrade'
  910. // (defined by WebSockets) where we need to remove a socket from the pool
  911. // because it'll be locked up indefinitely
  912. self.removeSocket(s, name, host, port, localAddress);
  913. s.removeListener('close', onClose);
  914. s.removeListener('free', onFree);
  915. s.removeListener('agentRemove', onRemove);
  916. }
  917. s.on('agentRemove', onRemove);
  918. return s;
  919. };
  920. Agent.prototype.removeSocket = function(s, name, host, port, localAddress) {
  921. if (this.sockets[name]) {
  922. var index = this.sockets[name].indexOf(s);
  923. if (index !== -1) {
  924. this.sockets[name].splice(index, 1);
  925. if (this.sockets[name].length === 0) {
  926. // don't leak
  927. delete this.sockets[name];
  928. }
  929. }
  930. }
  931. if (this.requests[name] && this.requests[name].length) {
  932. // If we have pending requests and a socket gets closed a new one
  933. this.createSocket(name, host, port, localAddress).emit('free');
  934. }
  935. };
  936. var globalAgent = new Agent();
  937. exports.globalAgent = globalAgent;
  938. function ClientRequest(options, cb) {
  939. var self = this;
  940. OutgoingMessage.call(self);
  941. self.agent = options.agent === undefined ? globalAgent : options.agent;
  942. var defaultPort = options.defaultPort || 80;
  943. var port = options.port || defaultPort;
  944. var host = options.hostname || options.host || 'localhost';
  945. if (options.setHost === undefined) {
  946. var setHost = true;
  947. }
  948. self.socketPath = options.socketPath;
  949. var method = self.method = (options.method || 'GET').toUpperCase();
  950. self.path = options.path || '/';
  951. if (cb) {
  952. self.once('response', cb);
  953. }
  954. if (!Array.isArray(options.headers)) {
  955. if (options.headers) {
  956. var keys = Object.keys(options.headers);
  957. for (var i = 0, l = keys.length; i < l; i++) {
  958. var key = keys[i];
  959. self.setHeader(key, options.headers[key]);
  960. }
  961. }
  962. if (host && !this.getHeader('host') && setHost) {
  963. var hostHeader = host;
  964. if (port && +port !== defaultPort) {
  965. hostHeader += ':' + port;
  966. }
  967. this.setHeader('Host', hostHeader);
  968. }
  969. }
  970. if (options.auth && !this.getHeader('Authorization')) {
  971. //basic auth
  972. this.setHeader('Authorization', 'Basic ' +
  973. new Buffer(options.auth).toString('base64'));
  974. }
  975. if (method === 'GET' || method === 'HEAD' || method === 'CONNECT') {
  976. self.useChunkedEncodingByDefault = false;
  977. } else {
  978. self.useChunkedEncodingByDefault = true;
  979. }
  980. if (Array.isArray(options.headers)) {
  981. self._storeHeader(self.method + ' ' + self.path + ' HTTP/1.1\r\n',
  982. options.headers);
  983. } else if (self.getHeader('expect')) {
  984. self._storeHeader(self.method + ' ' + self.path + ' HTTP/1.1\r\n',
  985. self._renderHeaders());
  986. }
  987. if (self.socketPath) {
  988. self._last = true;
  989. self.shouldKeepAlive = false;
  990. if (options.createConnection) {
  991. self.onSocket(options.createConnection(self.socketPath));
  992. } else {
  993. self.onSocket(net.createConnection(self.socketPath));
  994. }
  995. } else if (self.agent) {
  996. // If there is an agent we should default to Connection:keep-alive.
  997. self._last = false;
  998. self.shouldKeepAlive = true;
  999. self.agent.addRequest(self, host, port, options.localAddress);
  1000. } else {
  1001. // No agent, default to Connection:close.
  1002. self._last = true;
  1003. self.shouldKeepAlive = false;
  1004. if (options.createConnection) {
  1005. options.port = port;
  1006. options.host = host;
  1007. var conn = options.createConnection(options);
  1008. } else {
  1009. var conn = net.createConnection({
  1010. port: port,
  1011. host: host,
  1012. localAddress: options.localAddress
  1013. });
  1014. }
  1015. self.onSocket(conn);
  1016. }
  1017. self._deferToConnect(null, null, function() {
  1018. self._flush();
  1019. self = null;
  1020. });
  1021. }
  1022. util.inherits(ClientRequest, OutgoingMessage);
  1023. exports.ClientRequest = ClientRequest;
  1024. ClientRequest.prototype._implicitHeader = function() {
  1025. this._storeHeader(this.method + ' ' + this.path + ' HTTP/1.1\r\n',
  1026. this._renderHeaders());
  1027. };
  1028. ClientRequest.prototype.abort = function() {
  1029. if (this.socket) {
  1030. // in-progress
  1031. this.socket.destroy();
  1032. } else {
  1033. // haven't been assigned a socket yet.
  1034. // this could be more efficient, it could
  1035. // remove itself from the pending requests
  1036. this._deferToConnect('destroy', []);
  1037. }
  1038. };
  1039. function createHangUpError() {
  1040. var error = new Error('socket hang up');
  1041. error.code = 'ECONNRESET';
  1042. return error;
  1043. }
  1044. // Free the parser and also break any links that it
  1045. // might have to any other things.
  1046. // TODO: All parser data should be attached to a
  1047. // single object, so that it can be easily cleaned
  1048. // up by doing `parser.data = {}`, which should
  1049. // be done in FreeList.free. `parsers.free(parser)`
  1050. // should be all that is needed.
  1051. function freeParser(parser, req) {
  1052. if (parser) {
  1053. parser._headers = [];
  1054. parser.onIncoming = null;
  1055. if (parser.socket) {
  1056. parser.socket.onend = null;
  1057. parser.socket.ondata = null;
  1058. parser.socket.parser = null;
  1059. }
  1060. parser.socket = null;
  1061. parser.incoming = null;
  1062. parsers.free(parser);
  1063. parser = null;
  1064. }
  1065. if (req) {
  1066. req.parser = null;
  1067. }
  1068. }
  1069. function socketCloseListener() {
  1070. var socket = this;
  1071. var parser = socket.parser;
  1072. var req = socket._httpMessage;
  1073. debug('HTTP socket close');
  1074. req.emit('close');
  1075. if (req.res && req.res.readable) {
  1076. // Socket closed before we emitted 'end' below.
  1077. req.res.emit('aborted');
  1078. var res = req.res;
  1079. req.res._emitPending(function() {
  1080. res._emitEnd();
  1081. res.emit('close');
  1082. res = null;
  1083. });
  1084. } else if (!req.res && !req._hadError) {
  1085. // This socket error fired before we started to
  1086. // receive a response. The error needs to
  1087. // fire on the request.
  1088. req.emit('error', createHangUpError());
  1089. }
  1090. if (parser) {
  1091. parser.finish();
  1092. freeParser(parser, req);
  1093. }
  1094. }
  1095. function socketErrorListener(err) {
  1096. var socket = this;
  1097. var parser = socket.parser;
  1098. var req = socket._httpMessage;
  1099. debug('HTTP SOCKET ERROR: ' + err.message + '\n' + err.stack);
  1100. if (req) {
  1101. req.emit('error', err);
  1102. // For Safety. Some additional errors might fire later on
  1103. // and we need to make sure we don't double-fire the error event.
  1104. req._hadError = true;
  1105. }
  1106. if (parser) {
  1107. parser.finish();
  1108. freeParser(parser, req);
  1109. }
  1110. socket.destroy();
  1111. }
  1112. function socketOnEnd() {
  1113. var socket = this;
  1114. var req = this._httpMessage;
  1115. var parser = this.parser;
  1116. if (!req.res) {
  1117. // If we don't have a response then we know that the socket
  1118. // ended prematurely and we need to emit an error on the request.
  1119. req.emit('error', createHangUpError());
  1120. req._hadError = true;
  1121. }
  1122. if (parser) {
  1123. parser.finish();
  1124. freeParser(parser, req);
  1125. }
  1126. socket.destroy();
  1127. }
  1128. function socketOnData(d, start, end) {
  1129. var socket = this;
  1130. var req = this._httpMessage;
  1131. var parser = this.parser;
  1132. var ret = parser.execute(d, start, end - start);
  1133. if (ret instanceof Error) {
  1134. debug('parse error');
  1135. freeParser(parser, req);
  1136. socket.destroy(ret);
  1137. } else if (parser.incoming && parser.incoming.upgrade) {
  1138. // Upgrade or CONNECT
  1139. var bytesParsed = ret;
  1140. var res = parser.incoming;
  1141. req.res = res;
  1142. socket.ondata = null;
  1143. socket.onend = null;
  1144. parser.finish();
  1145. // This is start + byteParsed
  1146. var bodyHead = d.slice(start + bytesParsed, end);
  1147. var eventName = req.method === 'CONNECT' ? 'connect' : 'upgrade';
  1148. if (req.listeners(eventName).length) {
  1149. req.upgradeOrConnect = true;
  1150. // detach the socket
  1151. socket.emit('agentRemove');
  1152. socket.removeListener('close', socketCloseListener);
  1153. socket.removeListener('error', socketErrorListener);
  1154. req.emit(eventName, res, socket, bodyHead);
  1155. req.emit('close');
  1156. } else {
  1157. // Got Upgrade header or CONNECT method, but have no handler.
  1158. socket.destroy();
  1159. }
  1160. freeParser(parser, req);
  1161. } else if (parser.incoming && parser.incoming.complete &&
  1162. // When the status code is 100 (Continue), the server will
  1163. // send a final response after this client sends a request
  1164. // body. So, we must not free the parser.
  1165. parser.incoming.statusCode !== 100) {
  1166. freeParser(parser, req);
  1167. }
  1168. }
  1169. function parserOnIncomingClient(res, shouldKeepAlive) {
  1170. var parser = this;
  1171. var socket = this.socket;
  1172. var req = socket._httpMessage;
  1173. debug('AGENT incoming response!');
  1174. if (req.res) {
  1175. // We already have a response object, this means the server
  1176. // sent a double response.
  1177. socket.destroy();
  1178. return;
  1179. }
  1180. req.res = res;
  1181. // Responses to CONNECT request is handled as Upgrade.
  1182. if (req.method === 'CONNECT') {
  1183. res.upgrade = true;
  1184. return true; // skip body
  1185. }
  1186. // Responses to HEAD requests are crazy.
  1187. // HEAD responses aren't allowed to have an entity-body
  1188. // but *can* have a content-length which actually corresponds
  1189. // to the content-length of the entity-body had the request
  1190. // been a GET.
  1191. var isHeadResponse = req.method == 'HEAD';
  1192. debug('AGENT isHeadResponse ' + isHeadResponse);
  1193. if (res.statusCode == 100) {
  1194. // restart the parser, as this is a continue message.
  1195. delete req.res; // Clear res so that we don't hit double-responses.
  1196. req.emit('continue');
  1197. return true;
  1198. }
  1199. if (req.shouldKeepAlive && !shouldKeepAlive && !req.upgradeOrConnect) {
  1200. // Server MUST respond with Connection:keep-alive for us to enable it.
  1201. // If we've been upgraded (via WebSockets) we also shouldn't try to
  1202. // keep the connection open.
  1203. req.shouldKeepAlive = false;
  1204. }
  1205. DTRACE_HTTP_CLIENT_RESPONSE(socket, req);
  1206. req.emit('response', res);
  1207. req.res = res;
  1208. res.req = req;
  1209. res.on('end', responseOnEnd);
  1210. return isHeadResponse;
  1211. }
  1212. function responseOnEnd() {
  1213. var res = this;
  1214. var req = res.req;
  1215. var socket = req.socket;
  1216. if (!req.shouldKeepAlive) {
  1217. if (socket.writable) {
  1218. debug('AGENT socket.destroySoon()');
  1219. socket.destroySoon();
  1220. }
  1221. assert(!socket.writable);
  1222. } else {
  1223. debug('AGENT socket keep-alive');
  1224. socket.removeListener('close', socketCloseListener);
  1225. socket.removeListener('error', socketErrorListener);
  1226. socket.emit('free');
  1227. }
  1228. }
  1229. ClientRequest.prototype.onSocket = function(socket) {
  1230. var req = this;
  1231. process.nextTick(function() {
  1232. var parser = parsers.alloc();
  1233. req.socket = socket;
  1234. req.connection = socket;
  1235. parser.reinitialize(HTTPParser.RESPONSE);
  1236. parser.socket = socket;
  1237. parser.incoming = null;
  1238. req.parser = parser;
  1239. parser.socket = socket;
  1240. socket.parser = parser;
  1241. parser.incoming = null;
  1242. socket._httpMessage = req;
  1243. // Setup "drain" propogation.
  1244. httpSocketSetup(socket);
  1245. // Propagate headers limit from request object to parser
  1246. if (typeof req.maxHeadersCount === 'number') {
  1247. parser.maxHeaderPairs = req.maxHeadersCount << 1;
  1248. } else {
  1249. // Set default value because parser may be reused from FreeList
  1250. parser.maxHeaderPairs = 2000;
  1251. }
  1252. socket.on('error', socketErrorListener);
  1253. socket.ondata = socketOnData;
  1254. socket.onend = socketOnEnd;
  1255. socket.on('close', socketCloseListener);
  1256. parser.onIncoming = parserOnIncomingClient;
  1257. req.emit('socket', socket);
  1258. });
  1259. };
  1260. ClientRequest.prototype._deferToConnect = function(method, arguments_, cb) {
  1261. // This function is for calls that need to happen once the socket is
  1262. // connected and writable. It's an important promisy thing for all the socket
  1263. // calls that happen either now (when a socket is assigned) or
  1264. // in the future (when a socket gets assigned out of the pool and is
  1265. // eventually writable).
  1266. var self = this;
  1267. var onSocket = function() {
  1268. if (self.socket.writable) {
  1269. if (method) {
  1270. self.socket[method].apply(self.socket, arguments_);
  1271. }
  1272. if (cb) { cb(); }
  1273. } else {
  1274. self.socket.once('connect', function() {
  1275. if (method) {
  1276. self.socket[method].apply(self.socket, arguments_);
  1277. }
  1278. if (cb) { cb(); }
  1279. });
  1280. }
  1281. }
  1282. if (!self.socket) {
  1283. self.once('socket', onSocket);
  1284. } else {
  1285. onSocket();
  1286. }
  1287. };
  1288. ClientRequest.prototype.setTimeout = function(msecs, callback) {
  1289. if (callback) this.once('timeout', callback);
  1290. var self = this;
  1291. function emitTimeout() {
  1292. self.emit('timeout');
  1293. }
  1294. if (this.socket && this.socket.writable) {
  1295. this.socket.setTimeout(msecs, emitTimeout);
  1296. return;
  1297. }
  1298. if (this.socket) {
  1299. this.socket.once('connect', function() {
  1300. this.setTimeout(msecs, emitTimeout);
  1301. });
  1302. return;
  1303. }
  1304. this.once('socket', function(sock) {
  1305. this.setTimeout(msecs, emitTimeout);
  1306. });
  1307. };
  1308. ClientRequest.prototype.setNoDelay = function() {
  1309. this._deferToConnect('setNoDelay', arguments);
  1310. };
  1311. ClientRequest.prototype.setSocketKeepAlive = function() {
  1312. this._deferToConnect('setKeepAlive', arguments);
  1313. };
  1314. ClientRequest.prototype.clearTimeout = function(cb) {
  1315. this.setTimeout(0, cb);
  1316. };
  1317. exports.request = function(options, cb) {
  1318. if (typeof options === 'string') {
  1319. options = url.parse(options);
  1320. }
  1321. if (options.protocol && options.protocol !== 'http:') {
  1322. throw new Error('Protocol:' + options.protocol + ' not supported.');
  1323. }
  1324. return new ClientRequest(options, cb);
  1325. };
  1326. exports.get = function(options, cb) {
  1327. var req = exports.request(options, cb);
  1328. req.end();
  1329. return req;
  1330. };
  1331. function ondrain() {
  1332. if (this._httpMessage) this._httpMessage.emit('drain');
  1333. }
  1334. function httpSocketSetup(socket) {
  1335. socket.removeListener('drain', ondrain);
  1336. socket.on('drain', ondrain);
  1337. }
  1338. function Server(requestListener) {
  1339. if (!(this instanceof Server)) return new Server(requestListener);
  1340. net.Server.call(this, { allowHalfOpen: true });
  1341. if (requestListener) {
  1342. this.addListener('request', requestListener);
  1343. }
  1344. // Similar option to this. Too lazy to write my own docs.
  1345. // http://www.squid-cache.org/Doc/config/half_closed_clients/
  1346. // http://wiki.squid-cache.org/SquidFaq/InnerWorkings#What_is_a_half-closed_filedescriptor.3F
  1347. this.httpAllowHalfOpen = false;
  1348. this.addListener('connection', connectionListener);
  1349. }
  1350. util.inherits(Server, net.Server);
  1351. exports.Server = Server;
  1352. exports.createServer = function(requestListener) {
  1353. return new Server(requestListener);
  1354. };
  1355. function connectionListener(socket) {
  1356. var self = this;
  1357. var outgoing = [];
  1358. var incoming = [];
  1359. function abortIncoming() {
  1360. while (incoming.length) {
  1361. var req = incoming.shift();
  1362. req.emit('aborted');
  1363. req.emit('close');
  1364. }
  1365. // abort socket._httpMessage ?
  1366. }
  1367. function serverSocketCloseListener() {
  1368. debug('server socket close');
  1369. // mark this parser as reusable
  1370. freeParser(parser);
  1371. abortIncoming();
  1372. }
  1373. debug('SERVER new http connection');
  1374. httpSocketSetup(socket);
  1375. socket.setTimeout(2 * 60 * 1000); // 2 minute timeout
  1376. socket.once('timeout', function() {
  1377. socket.destroy();
  1378. });
  1379. var parser = parsers.alloc();
  1380. parser.reinitialize(HTTPParser.REQUEST);
  1381. parser.socket = socket;
  1382. socket.parser = parser;
  1383. parser.incoming = null;
  1384. // Propagate headers limit from server instance to parser
  1385. if (typeof this.maxHeadersCount === 'number') {
  1386. parser.maxHeaderPairs = this.maxHeadersCount << 1;
  1387. } else {
  1388. // Set default value because parser may be reused from FreeList
  1389. parser.maxHeaderPairs = 2000;
  1390. }
  1391. socket.addListener('error', function(e) {
  1392. self.emit('clientError', e);
  1393. });
  1394. socket.ondata = function(d, start, end) {
  1395. var ret = parser.execute(d, start, end - start);
  1396. if (ret instanceof Error) {
  1397. debug('parse error');
  1398. socket.destroy(ret);
  1399. } else if (parser.incoming && parser.incoming.upgrade) {
  1400. // Upgrade or CONNECT
  1401. var bytesParsed = ret;
  1402. var req = parser.incoming;
  1403. socket.ondata = null;
  1404. socket.onend = null;
  1405. socket.removeListener('close', serverSocketCloseListener);
  1406. parser.finish();
  1407. freeParser(parser, req);
  1408. // This is start + byteParsed
  1409. var bodyHead = d.slice(start + bytesParsed, end);
  1410. var eventName = req.method === 'CONNECT' ? 'connect' : 'upgrade';
  1411. if (self.listeners(eventName).length) {
  1412. self.emit(eventName, req, req.socket, bodyHead);
  1413. } else {
  1414. // Got upgrade header or CONNECT method, but have no handler.
  1415. socket.destroy();
  1416. }
  1417. }
  1418. };
  1419. socket.onend = function() {
  1420. var ret = parser.finish();
  1421. if (ret instanceof Error) {
  1422. debug('parse error');
  1423. socket.destroy(ret);
  1424. return;
  1425. }
  1426. if (!self.httpAllowHalfOpen) {
  1427. abortIncoming();
  1428. if (socket.writable) socket.end();
  1429. } else if (outgoing.length) {
  1430. outgoing[outgoing.length - 1]._last = true;
  1431. } else if (socket._httpMessage) {
  1432. socket._httpMessage._last = true;
  1433. } else {
  1434. if (socket.writable) socket.end();
  1435. }
  1436. };
  1437. socket.addListener('close', serverSocketCloseListener);
  1438. // The following callback is issued after the headers have been read on a
  1439. // new message. In this callback we setup the response object and pass it
  1440. // to the user.
  1441. parser.onIncoming = function(req, shouldKeepAlive) {
  1442. incoming.push(req);
  1443. var res = new ServerResponse(req);
  1444. debug('server response shouldKeepAlive: ' + shouldKeepAlive);
  1445. res.shouldKeepAlive = shouldKeepAlive;
  1446. DTRACE_HTTP_SERVER_REQUEST(req, socket);
  1447. if (socket._httpMessage) {
  1448. // There are already pending outgoing res, append.
  1449. outgoing.push(res);
  1450. } else {
  1451. res.assignSocket(socket);
  1452. }
  1453. // When we're finished writing the response, check if this is the last
  1454. // respose, if so destroy the socket.
  1455. res.on('finish', function() {
  1456. // Usually the first incoming element should be our request. it may
  1457. // be that in the case abortIncoming() was called that the incoming
  1458. // array will be empty.
  1459. assert(incoming.length == 0 || incoming[0] === req);
  1460. incoming.shift();
  1461. res.detachSocket(socket);
  1462. if (res._last) {
  1463. socket.destroySoon();
  1464. } else {
  1465. // start sending the next message
  1466. var m = outgoing.shift();
  1467. if (m) {
  1468. m.assignSocket(socket);
  1469. }
  1470. }
  1471. });
  1472. if ('expect' in req.headers &&
  1473. (req.httpVersionMajor == 1 && req.httpVersionMinor == 1) &&
  1474. continueExpression.test(req.headers['expect'])) {
  1475. res._expect_continue = true;
  1476. if (self.listeners('checkContinue').length) {
  1477. self.emit('checkContinue', req, res);
  1478. } else {
  1479. res.writeContinue();
  1480. self.emit('request', req, res);
  1481. }
  1482. } else {
  1483. self.emit('request', req, res);
  1484. }
  1485. return false; // Not a HEAD response. (Not even a response!)
  1486. };
  1487. }
  1488. exports._connectionListener = connectionListener;
  1489. // Legacy Interface
  1490. function Client(port, host) {
  1491. if (!(this instanceof Client)) return new Client(port, host);
  1492. host = host || 'localhost';
  1493. port = port || 80;
  1494. this.host = host;
  1495. this.port = port;
  1496. this.agent = new Agent({ host: host, port: port, maxSockets: 1 });
  1497. }
  1498. util.inherits(Client, EventEmitter);
  1499. Client.prototype.request = function(method, path, headers) {
  1500. var self = this;
  1501. var options = {};
  1502. options.host = self.host;
  1503. options.port = self.port;
  1504. if (method[0] === '/') {
  1505. headers = path;
  1506. path = method;
  1507. method = 'GET';
  1508. }
  1509. options.method = method;
  1510. options.path = path;
  1511. options.headers = headers;
  1512. options.agent = self.agent;
  1513. var c = new ClientRequest(options);
  1514. c.on('error', function(e) {
  1515. self.emit('error', e);
  1516. });
  1517. // The old Client interface emitted 'end' on socket end.
  1518. // This doesn't map to how we want things to operate in the future
  1519. // but it will get removed when we remove this legacy interface.
  1520. c.on('socket', function(s) {
  1521. s.on('end', function() {
  1522. self.emit('end');
  1523. });
  1524. });
  1525. return c;
  1526. };
  1527. exports.Client = Client;
  1528. // TODO http.Client can be removed in v0.9. Until then leave this message.
  1529. module.deprecate('Client', 'It will be removed soon. Do not use it.');
  1530. exports.createClient = function(port, host) {
  1531. return new Client(port, host);
  1532. };
  1533. module.deprecate('createClient', 'Use `http.request` instead.');