PageRenderTime 51ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/_http_incoming.js

https://gitlab.com/GeekSir/node
JavaScript | 198 lines | 115 code | 34 blank | 49 comment | 19 complexity | e740b1936914a0d89c74dbd31ab506a9 MD5 | raw file
Possible License(s): 0BSD, Apache-2.0, MPL-2.0-no-copyleft-exception, JSON, WTFPL, CC-BY-SA-3.0, Unlicense, ISC, BSD-3-Clause, MIT, AGPL-3.0
  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. 'use strict';
  22. var util = require('util');
  23. var Stream = require('stream');
  24. function readStart(socket) {
  25. if (socket && !socket._paused && socket.readable)
  26. socket.resume();
  27. }
  28. exports.readStart = readStart;
  29. function readStop(socket) {
  30. if (socket)
  31. socket.pause();
  32. }
  33. exports.readStop = readStop;
  34. /* Abstract base class for ServerRequest and ClientResponse. */
  35. function IncomingMessage(socket) {
  36. Stream.Readable.call(this);
  37. // XXX This implementation is kind of all over the place
  38. // When the parser emits body chunks, they go in this list.
  39. // _read() pulls them out, and when it finds EOF, it ends.
  40. this.socket = socket;
  41. this.connection = socket;
  42. this.httpVersionMajor = null;
  43. this.httpVersionMinor = null;
  44. this.httpVersion = null;
  45. this.complete = false;
  46. this.headers = {};
  47. this.rawHeaders = [];
  48. this.trailers = {};
  49. this.rawTrailers = [];
  50. this.readable = true;
  51. this._pendings = [];
  52. this._pendingIndex = 0;
  53. this.upgrade = null;
  54. // request (server) only
  55. this.url = '';
  56. this.method = null;
  57. // response (client) only
  58. this.statusCode = null;
  59. this.statusMessage = null;
  60. this.client = this.socket;
  61. // flag for backwards compatibility grossness.
  62. this._consuming = false;
  63. // flag for when we decide that this message cannot possibly be
  64. // read by the user, so there's no point continuing to handle it.
  65. this._dumped = false;
  66. }
  67. util.inherits(IncomingMessage, Stream.Readable);
  68. exports.IncomingMessage = IncomingMessage;
  69. IncomingMessage.prototype.setTimeout = function(msecs, callback) {
  70. if (callback)
  71. this.on('timeout', callback);
  72. this.socket.setTimeout(msecs);
  73. };
  74. IncomingMessage.prototype.read = function(n) {
  75. this._consuming = true;
  76. this.read = Stream.Readable.prototype.read;
  77. return this.read(n);
  78. };
  79. IncomingMessage.prototype._read = function(n) {
  80. // We actually do almost nothing here, because the parserOnBody
  81. // function fills up our internal buffer directly. However, we
  82. // do need to unpause the underlying socket so that it flows.
  83. if (this.socket.readable)
  84. readStart(this.socket);
  85. };
  86. // It's possible that the socket will be destroyed, and removed from
  87. // any messages, before ever calling this. In that case, just skip
  88. // it, since something else is destroying this connection anyway.
  89. IncomingMessage.prototype.destroy = function(error) {
  90. if (this.socket)
  91. this.socket.destroy(error);
  92. };
  93. IncomingMessage.prototype._addHeaderLines = function(headers, n) {
  94. if (headers && headers.length) {
  95. var raw, dest;
  96. if (this.complete) {
  97. raw = this.rawTrailers;
  98. dest = this.trailers;
  99. } else {
  100. raw = this.rawHeaders;
  101. dest = this.headers;
  102. }
  103. for (var i = 0; i < n; i += 2) {
  104. var k = headers[i];
  105. var v = headers[i + 1];
  106. raw.push(k);
  107. raw.push(v);
  108. this._addHeaderLine(k, v, dest);
  109. }
  110. }
  111. };
  112. // Add the given (field, value) pair to the message
  113. //
  114. // Per RFC2616, section 4.2 it is acceptable to join multiple instances of the
  115. // same header with a ', ' if the header in question supports specification of
  116. // multiple values this way. If not, we declare the first instance the winner
  117. // and drop the second. Extended header fields (those beginning with 'x-') are
  118. // always joined.
  119. IncomingMessage.prototype._addHeaderLine = function(field, value, dest) {
  120. field = field.toLowerCase();
  121. switch (field) {
  122. // Array headers:
  123. case 'set-cookie':
  124. if (!util.isUndefined(dest[field])) {
  125. dest[field].push(value);
  126. } else {
  127. dest[field] = [value];
  128. }
  129. break;
  130. // list is taken from:
  131. // https://mxr.mozilla.org/mozilla/source/netwerk/protocol/http/src/nsHttpHeaderArray.cpp
  132. case 'content-type':
  133. case 'content-length':
  134. case 'user-agent':
  135. case 'referer':
  136. case 'host':
  137. case 'authorization':
  138. case 'proxy-authorization':
  139. case 'if-modified-since':
  140. case 'if-unmodified-since':
  141. case 'from':
  142. case 'location':
  143. case 'max-forwards':
  144. // drop duplicates
  145. if (util.isUndefined(dest[field]))
  146. dest[field] = value;
  147. break;
  148. default:
  149. // make comma-separated list
  150. if (!util.isUndefined(dest[field]))
  151. dest[field] += ', ' + value;
  152. else {
  153. dest[field] = value;
  154. }
  155. }
  156. };
  157. // Call this instead of resume() if we want to just
  158. // dump all the data to /dev/null
  159. IncomingMessage.prototype._dump = function() {
  160. if (!this._dumped) {
  161. this._dumped = true;
  162. this.resume();
  163. }
  164. };