• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright Joyent, Inc. and other Node contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a
4// copy of this software and associated documentation files (the
5// "Software"), to deal in the Software without restriction, including
6// without limitation the rights to use, copy, modify, merge, publish,
7// distribute, sublicense, and/or sell copies of the Software, and to permit
8// persons to whom the Software is furnished to do so, subject to the
9// following conditions:
10//
11// The above copyright notice and this permission notice shall be included
12// in all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20// USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22'use strict';
23
24const {
25  ArrayIsArray,
26  Error,
27  MathMin,
28  ObjectKeys,
29  ObjectSetPrototypeOf,
30  RegExpPrototypeExec,
31  ReflectApply,
32  Symbol,
33  SymbolFor,
34} = primordials;
35
36const net = require('net');
37const EE = require('events');
38const assert = require('internal/assert');
39const {
40  parsers,
41  freeParser,
42  continueExpression,
43  chunkExpression,
44  kIncomingMessage,
45  HTTPParser,
46  isLenient,
47  _checkInvalidHeaderChar: checkInvalidHeaderChar,
48  prepareError,
49} = require('_http_common');
50const { ConnectionsList } = internalBinding('http_parser');
51const {
52  kUniqueHeaders,
53  parseUniqueHeadersOption,
54  OutgoingMessage,
55} = require('_http_outgoing');
56const {
57  kOutHeaders,
58  kNeedDrain,
59  isTraceHTTPEnabled,
60  traceBegin,
61  traceEnd,
62  getNextTraceEventId,
63} = require('internal/http');
64const {
65  defaultTriggerAsyncIdScope,
66  getOrSetAsyncId,
67} = require('internal/async_hooks');
68const { IncomingMessage } = require('_http_incoming');
69const {
70  connResetException,
71  codes,
72} = require('internal/errors');
73const {
74  ERR_HTTP_REQUEST_TIMEOUT,
75  ERR_HTTP_HEADERS_SENT,
76  ERR_HTTP_INVALID_STATUS_CODE,
77  ERR_HTTP_SOCKET_ENCODING,
78  ERR_INVALID_ARG_TYPE,
79  ERR_HTTP_SOCKET_ASSIGNED,
80  ERR_INVALID_ARG_VALUE,
81  ERR_INVALID_CHAR,
82} = codes;
83const {
84  validateInteger,
85  validateBoolean,
86  validateLinkHeaderValue,
87  validateObject,
88} = require('internal/validators');
89const Buffer = require('buffer').Buffer;
90const {
91  DTRACE_HTTP_SERVER_REQUEST,
92  DTRACE_HTTP_SERVER_RESPONSE,
93} = require('internal/dtrace');
94const { setInterval, clearInterval } = require('timers');
95let debug = require('internal/util/debuglog').debuglog('http', (fn) => {
96  debug = fn;
97});
98
99const dc = require('diagnostics_channel');
100const onRequestStartChannel = dc.channel('http.server.request.start');
101const onResponseFinishChannel = dc.channel('http.server.response.finish');
102
103const kServerResponse = Symbol('ServerResponse');
104const kServerResponseStatistics = Symbol('ServerResponseStatistics');
105
106const {
107  hasObserver,
108  startPerf,
109  stopPerf,
110} = require('internal/perf/observe');
111
112const STATUS_CODES = {
113  100: 'Continue',                   // RFC 7231 6.2.1
114  101: 'Switching Protocols',        // RFC 7231 6.2.2
115  102: 'Processing',                 // RFC 2518 10.1 (obsoleted by RFC 4918)
116  103: 'Early Hints',                // RFC 8297 2
117  200: 'OK',                         // RFC 7231 6.3.1
118  201: 'Created',                    // RFC 7231 6.3.2
119  202: 'Accepted',                   // RFC 7231 6.3.3
120  203: 'Non-Authoritative Information', // RFC 7231 6.3.4
121  204: 'No Content',                 // RFC 7231 6.3.5
122  205: 'Reset Content',              // RFC 7231 6.3.6
123  206: 'Partial Content',            // RFC 7233 4.1
124  207: 'Multi-Status',               // RFC 4918 11.1
125  208: 'Already Reported',           // RFC 5842 7.1
126  226: 'IM Used',                    // RFC 3229 10.4.1
127  300: 'Multiple Choices',           // RFC 7231 6.4.1
128  301: 'Moved Permanently',          // RFC 7231 6.4.2
129  302: 'Found',                      // RFC 7231 6.4.3
130  303: 'See Other',                  // RFC 7231 6.4.4
131  304: 'Not Modified',               // RFC 7232 4.1
132  305: 'Use Proxy',                  // RFC 7231 6.4.5
133  307: 'Temporary Redirect',         // RFC 7231 6.4.7
134  308: 'Permanent Redirect',         // RFC 7238 3
135  400: 'Bad Request',                // RFC 7231 6.5.1
136  401: 'Unauthorized',               // RFC 7235 3.1
137  402: 'Payment Required',           // RFC 7231 6.5.2
138  403: 'Forbidden',                  // RFC 7231 6.5.3
139  404: 'Not Found',                  // RFC 7231 6.5.4
140  405: 'Method Not Allowed',         // RFC 7231 6.5.5
141  406: 'Not Acceptable',             // RFC 7231 6.5.6
142  407: 'Proxy Authentication Required', // RFC 7235 3.2
143  408: 'Request Timeout',            // RFC 7231 6.5.7
144  409: 'Conflict',                   // RFC 7231 6.5.8
145  410: 'Gone',                       // RFC 7231 6.5.9
146  411: 'Length Required',            // RFC 7231 6.5.10
147  412: 'Precondition Failed',        // RFC 7232 4.2
148  413: 'Payload Too Large',          // RFC 7231 6.5.11
149  414: 'URI Too Long',               // RFC 7231 6.5.12
150  415: 'Unsupported Media Type',     // RFC 7231 6.5.13
151  416: 'Range Not Satisfiable',      // RFC 7233 4.4
152  417: 'Expectation Failed',         // RFC 7231 6.5.14
153  418: 'I\'m a Teapot',              // RFC 7168 2.3.3
154  421: 'Misdirected Request',        // RFC 7540 9.1.2
155  422: 'Unprocessable Entity',       // RFC 4918 11.2
156  423: 'Locked',                     // RFC 4918 11.3
157  424: 'Failed Dependency',          // RFC 4918 11.4
158  425: 'Too Early',                  // RFC 8470 5.2
159  426: 'Upgrade Required',           // RFC 2817 and RFC 7231 6.5.15
160  428: 'Precondition Required',      // RFC 6585 3
161  429: 'Too Many Requests',          // RFC 6585 4
162  431: 'Request Header Fields Too Large', // RFC 6585 5
163  451: 'Unavailable For Legal Reasons', // RFC 7725 3
164  500: 'Internal Server Error',      // RFC 7231 6.6.1
165  501: 'Not Implemented',            // RFC 7231 6.6.2
166  502: 'Bad Gateway',                // RFC 7231 6.6.3
167  503: 'Service Unavailable',        // RFC 7231 6.6.4
168  504: 'Gateway Timeout',            // RFC 7231 6.6.5
169  505: 'HTTP Version Not Supported', // RFC 7231 6.6.6
170  506: 'Variant Also Negotiates',    // RFC 2295 8.1
171  507: 'Insufficient Storage',       // RFC 4918 11.5
172  508: 'Loop Detected',              // RFC 5842 7.2
173  509: 'Bandwidth Limit Exceeded',
174  510: 'Not Extended',               // RFC 2774 7
175  511: 'Network Authentication Required', // RFC 6585 6
176};
177
178const kOnExecute = HTTPParser.kOnExecute | 0;
179const kOnTimeout = HTTPParser.kOnTimeout | 0;
180const kLenientAll = HTTPParser.kLenientAll | 0;
181const kLenientNone = HTTPParser.kLenientNone | 0;
182const kConnections = Symbol('http.server.connections');
183const kConnectionsCheckingInterval = Symbol('http.server.connectionsCheckingInterval');
184
185const HTTP_SERVER_TRACE_EVENT_NAME = 'http.server.request';
186
187class HTTPServerAsyncResource {
188  constructor(type, socket) {
189    this.type = type;
190    this.socket = socket;
191  }
192}
193
194function ServerResponse(req, options) {
195  OutgoingMessage.call(this, options);
196
197  if (req.method === 'HEAD') this._hasBody = false;
198
199  this.req = req;
200  this.sendDate = true;
201  this._sent100 = false;
202  this._expect_continue = false;
203
204  if (req.httpVersionMajor < 1 || req.httpVersionMinor < 1) {
205    this.useChunkedEncodingByDefault = RegExpPrototypeExec(chunkExpression,
206                                                           req.headers.te) !== null;
207    this.shouldKeepAlive = false;
208  }
209
210  if (hasObserver('http')) {
211    startPerf(this, kServerResponseStatistics, {
212      type: 'http',
213      name: 'HttpRequest',
214      detail: {
215        req: {
216          method: req.method,
217          url: req.url,
218          headers: req.headers,
219        },
220      },
221    });
222  }
223  if (isTraceHTTPEnabled()) {
224    this._traceEventId = getNextTraceEventId();
225    traceBegin(HTTP_SERVER_TRACE_EVENT_NAME, this._traceEventId);
226  }
227}
228ObjectSetPrototypeOf(ServerResponse.prototype, OutgoingMessage.prototype);
229ObjectSetPrototypeOf(ServerResponse, OutgoingMessage);
230
231ServerResponse.prototype._finish = function _finish() {
232  DTRACE_HTTP_SERVER_RESPONSE(this.socket);
233  if (this[kServerResponseStatistics] && hasObserver('http')) {
234    stopPerf(this, kServerResponseStatistics, {
235      detail: {
236        res: {
237          statusCode: this.statusCode,
238          statusMessage: this.statusMessage,
239          headers: typeof this.getHeaders === 'function' ? this.getHeaders() : {},
240        },
241      },
242    });
243  }
244  OutgoingMessage.prototype._finish.call(this);
245  if (isTraceHTTPEnabled() && typeof this._traceEventId === 'number') {
246    const data = {
247      url: this.req?.url,
248      statusCode: this.statusCode,
249    };
250    traceEnd(HTTP_SERVER_TRACE_EVENT_NAME, this._traceEventId, data);
251  }
252};
253
254
255ServerResponse.prototype.statusCode = 200;
256ServerResponse.prototype.statusMessage = undefined;
257
258function onServerResponseClose() {
259  // EventEmitter.emit makes a copy of the 'close' listeners array before
260  // calling the listeners. detachSocket() unregisters onServerResponseClose
261  // but if detachSocket() is called, directly or indirectly, by a 'close'
262  // listener, onServerResponseClose is still in that copy of the listeners
263  // array. That is, in the example below, b still gets called even though
264  // it's been removed by a:
265  //
266  //   const EventEmitter = require('events');
267  //   const obj = new EventEmitter();
268  //   obj.on('event', a);
269  //   obj.on('event', b);
270  //   function a() { obj.removeListener('event', b) }
271  //   function b() { throw "BAM!" }
272  //   obj.emit('event');  // throws
273  //
274  // Ergo, we need to deal with stale 'close' events and handle the case
275  // where the ServerResponse object has already been deconstructed.
276  // Fortunately, that requires only a single if check. :-)
277  if (this._httpMessage) {
278    emitCloseNT(this._httpMessage);
279  }
280}
281
282ServerResponse.prototype.assignSocket = function assignSocket(socket) {
283  if (socket._httpMessage) {
284    throw new ERR_HTTP_SOCKET_ASSIGNED();
285  }
286  socket._httpMessage = this;
287  socket.on('close', onServerResponseClose);
288  this.socket = socket;
289  this.emit('socket', socket);
290  this._flush();
291};
292
293ServerResponse.prototype.detachSocket = function detachSocket(socket) {
294  assert(socket._httpMessage === this);
295  socket.removeListener('close', onServerResponseClose);
296  socket._httpMessage = null;
297  this.socket = null;
298};
299
300ServerResponse.prototype.writeContinue = function writeContinue(cb) {
301  this._writeRaw('HTTP/1.1 100 Continue\r\n\r\n', 'ascii', cb);
302  this._sent100 = true;
303};
304
305ServerResponse.prototype.writeProcessing = function writeProcessing(cb) {
306  this._writeRaw('HTTP/1.1 102 Processing\r\n\r\n', 'ascii', cb);
307};
308
309ServerResponse.prototype.writeEarlyHints = function writeEarlyHints(hints, cb) {
310  let head = 'HTTP/1.1 103 Early Hints\r\n';
311
312  validateObject(hints, 'hints');
313
314  if (hints.link === null || hints.link === undefined) {
315    return;
316  }
317
318  const link = validateLinkHeaderValue(hints.link);
319
320  if (link.length === 0) {
321    return;
322  }
323
324  head += 'Link: ' + link + '\r\n';
325
326  for (const key of ObjectKeys(hints)) {
327    if (key !== 'link') {
328      head += key + ': ' + hints[key] + '\r\n';
329    }
330  }
331
332  head += '\r\n';
333
334  this._writeRaw(head, 'ascii', cb);
335};
336
337ServerResponse.prototype._implicitHeader = function _implicitHeader() {
338  this.writeHead(this.statusCode);
339};
340
341ServerResponse.prototype.writeHead = writeHead;
342function writeHead(statusCode, reason, obj) {
343  const originalStatusCode = statusCode;
344
345  statusCode |= 0;
346  if (statusCode < 100 || statusCode > 999) {
347    throw new ERR_HTTP_INVALID_STATUS_CODE(originalStatusCode);
348  }
349
350
351  if (typeof reason === 'string') {
352    // writeHead(statusCode, reasonPhrase[, headers])
353    this.statusMessage = reason;
354  } else {
355    // writeHead(statusCode[, headers])
356    if (!this.statusMessage)
357      this.statusMessage = STATUS_CODES[statusCode] || 'unknown';
358    obj ??= reason;
359  }
360  this.statusCode = statusCode;
361
362  let headers;
363  if (this[kOutHeaders]) {
364    // Slow-case: when progressive API and header fields are passed.
365    let k;
366    if (ArrayIsArray(obj)) {
367      if (obj.length % 2 !== 0) {
368        throw new ERR_INVALID_ARG_VALUE('headers', obj);
369      }
370
371      for (let n = 0; n < obj.length; n += 2) {
372        k = obj[n + 0];
373        if (k) this.setHeader(k, obj[n + 1]);
374      }
375    } else if (obj) {
376      const keys = ObjectKeys(obj);
377      // Retain for(;;) loop for performance reasons
378      // Refs: https://github.com/nodejs/node/pull/30958
379      for (let i = 0; i < keys.length; i++) {
380        k = keys[i];
381        if (k) this.setHeader(k, obj[k]);
382      }
383    }
384    if (k === undefined && this._header) {
385      throw new ERR_HTTP_HEADERS_SENT('render');
386    }
387    // Only progressive api is used
388    headers = this[kOutHeaders];
389  } else {
390    // Only writeHead() called
391    headers = obj;
392  }
393
394  if (checkInvalidHeaderChar(this.statusMessage))
395    throw new ERR_INVALID_CHAR('statusMessage');
396
397  const statusLine = `HTTP/1.1 ${statusCode} ${this.statusMessage}\r\n`;
398
399  if (statusCode === 204 || statusCode === 304 ||
400      (statusCode >= 100 && statusCode <= 199)) {
401    // RFC 2616, 10.2.5:
402    // The 204 response MUST NOT include a message-body, and thus is always
403    // terminated by the first empty line after the header fields.
404    // RFC 2616, 10.3.5:
405    // The 304 response MUST NOT contain a message-body, and thus is always
406    // terminated by the first empty line after the header fields.
407    // RFC 2616, 10.1 Informational 1xx:
408    // This class of status code indicates a provisional response,
409    // consisting only of the Status-Line and optional headers, and is
410    // terminated by an empty line.
411    this._hasBody = false;
412  }
413
414  // Don't keep alive connections where the client expects 100 Continue
415  // but we sent a final status; they may put extra bytes on the wire.
416  if (this._expect_continue && !this._sent100) {
417    this.shouldKeepAlive = false;
418  }
419
420  this._storeHeader(statusLine, headers);
421
422  return this;
423}
424
425// Docs-only deprecated: DEP0063
426ServerResponse.prototype.writeHeader = ServerResponse.prototype.writeHead;
427
428function storeHTTPOptions(options) {
429  this[kIncomingMessage] = options.IncomingMessage || IncomingMessage;
430  this[kServerResponse] = options.ServerResponse || ServerResponse;
431
432  const maxHeaderSize = options.maxHeaderSize;
433  if (maxHeaderSize !== undefined)
434    validateInteger(maxHeaderSize, 'maxHeaderSize', 0);
435  this.maxHeaderSize = maxHeaderSize;
436
437  const insecureHTTPParser = options.insecureHTTPParser;
438  if (insecureHTTPParser !== undefined)
439    validateBoolean(insecureHTTPParser, 'options.insecureHTTPParser');
440  this.insecureHTTPParser = insecureHTTPParser;
441
442  if (options.noDelay === undefined)
443    options.noDelay = true;
444
445  const requestTimeout = options.requestTimeout;
446  if (requestTimeout !== undefined) {
447    validateInteger(requestTimeout, 'requestTimeout', 0);
448    this.requestTimeout = requestTimeout;
449  } else {
450    this.requestTimeout = 300_000; // 5 minutes
451  }
452
453  const headersTimeout = options.headersTimeout;
454  if (headersTimeout !== undefined) {
455    validateInteger(headersTimeout, 'headersTimeout', 0);
456    this.headersTimeout = headersTimeout;
457  } else {
458    this.headersTimeout = MathMin(60_000, this.requestTimeout); // Minimum between 60 seconds or requestTimeout
459  }
460
461  if (this.requestTimeout > 0 && this.headersTimeout > 0 && this.headersTimeout > this.requestTimeout) {
462    throw new codes.ERR_OUT_OF_RANGE('headersTimeout', '<= requestTimeout', headersTimeout);
463  }
464
465  const keepAliveTimeout = options.keepAliveTimeout;
466  if (keepAliveTimeout !== undefined) {
467    validateInteger(keepAliveTimeout, 'keepAliveTimeout', 0);
468    this.keepAliveTimeout = keepAliveTimeout;
469  } else {
470    this.keepAliveTimeout = 5_000; // 5 seconds;
471  }
472
473  const connectionsCheckingInterval = options.connectionsCheckingInterval;
474  if (connectionsCheckingInterval !== undefined) {
475    validateInteger(connectionsCheckingInterval, 'connectionsCheckingInterval', 0);
476    this.connectionsCheckingInterval = connectionsCheckingInterval;
477  } else {
478    this.connectionsCheckingInterval = 30_000; // 30 seconds
479  }
480
481  const joinDuplicateHeaders = options.joinDuplicateHeaders;
482  if (joinDuplicateHeaders !== undefined) {
483    validateBoolean(joinDuplicateHeaders, 'options.joinDuplicateHeaders');
484  }
485  this.joinDuplicateHeaders = joinDuplicateHeaders;
486
487  const rejectNonStandardBodyWrites = options.rejectNonStandardBodyWrites;
488  if (rejectNonStandardBodyWrites !== undefined) {
489    validateBoolean(rejectNonStandardBodyWrites, 'options.rejectNonStandardBodyWrites');
490    this.rejectNonStandardBodyWrites = rejectNonStandardBodyWrites;
491  } else {
492    this.rejectNonStandardBodyWrites = false;
493  }
494}
495
496function setupConnectionsTracking(server) {
497  // Start connection handling
498  server[kConnections] = new ConnectionsList();
499
500  // This checker is started without checking whether any headersTimeout or requestTimeout is non zero
501  // otherwise it would not be started if such timeouts are modified after createServer.
502  server[kConnectionsCheckingInterval] =
503    setInterval(checkConnections.bind(server), server.connectionsCheckingInterval).unref();
504}
505
506function Server(options, requestListener) {
507  if (!(this instanceof Server)) return new Server(options, requestListener);
508
509  if (typeof options === 'function') {
510    requestListener = options;
511    options = {};
512  } else if (options == null || typeof options === 'object') {
513    options = { ...options };
514  } else {
515    throw new ERR_INVALID_ARG_TYPE('options', 'object', options);
516  }
517
518  storeHTTPOptions.call(this, options);
519  net.Server.call(
520    this,
521    { allowHalfOpen: true, noDelay: options.noDelay,
522      keepAlive: options.keepAlive,
523      keepAliveInitialDelay: options.keepAliveInitialDelay,
524      highWaterMark: options.highWaterMark });
525
526  if (requestListener) {
527    this.on('request', requestListener);
528  }
529
530  // Similar option to this. Too lazy to write my own docs.
531  // http://www.squid-cache.org/Doc/config/half_closed_clients/
532  // https://wiki.squid-cache.org/SquidFaq/InnerWorkings#What_is_a_half-closed_filedescriptor.3F
533  this.httpAllowHalfOpen = false;
534
535  this.on('connection', connectionListener);
536
537  this.timeout = 0;
538  this.maxHeadersCount = null;
539  this.maxRequestsPerSocket = 0;
540  setupConnectionsTracking(this);
541  this[kUniqueHeaders] = parseUniqueHeadersOption(options.uniqueHeaders);
542}
543ObjectSetPrototypeOf(Server.prototype, net.Server.prototype);
544ObjectSetPrototypeOf(Server, net.Server);
545
546Server.prototype.close = function() {
547  clearInterval(this[kConnectionsCheckingInterval]);
548  ReflectApply(net.Server.prototype.close, this, arguments);
549};
550
551Server.prototype.closeAllConnections = function() {
552  const connections = this[kConnections].all();
553
554  for (let i = 0, l = connections.length; i < l; i++) {
555    connections[i].socket.destroy();
556  }
557};
558
559Server.prototype.closeIdleConnections = function() {
560  const connections = this[kConnections].idle();
561
562  for (let i = 0, l = connections.length; i < l; i++) {
563    if (connections[i].socket._httpMessage && !connections[i].socket._httpMessage.finished) {
564      continue;
565    }
566
567    connections[i].socket.destroy();
568  }
569};
570
571Server.prototype.setTimeout = function setTimeout(msecs, callback) {
572  this.timeout = msecs;
573  if (callback)
574    this.on('timeout', callback);
575  return this;
576};
577
578Server.prototype[EE.captureRejectionSymbol] = function(err, event, ...args) {
579  switch (event) {
580    case 'request': {
581      const { 1: res } = args;
582      if (!res.headersSent && !res.writableEnded) {
583        // Don't leak headers.
584        const names = res.getHeaderNames();
585        for (let i = 0; i < names.length; i++) {
586          res.removeHeader(names[i]);
587        }
588        res.statusCode = 500;
589        res.end(STATUS_CODES[500]);
590      } else {
591        res.destroy();
592      }
593      break;
594    }
595    default:
596      net.Server.prototype[SymbolFor('nodejs.rejection')]
597        .apply(this, arguments);
598  }
599};
600
601function checkConnections() {
602  if (this.headersTimeout === 0 && this.requestTimeout === 0) {
603    return;
604  }
605
606  const expired = this[kConnections].expired(this.headersTimeout, this.requestTimeout);
607
608  for (let i = 0; i < expired.length; i++) {
609    const socket = expired[i].socket;
610
611    if (socket) {
612      onRequestTimeout(socket);
613    }
614  }
615}
616
617function connectionListener(socket) {
618  defaultTriggerAsyncIdScope(
619    getOrSetAsyncId(socket), connectionListenerInternal, this, socket,
620  );
621}
622
623function connectionListenerInternal(server, socket) {
624  debug('SERVER new http connection');
625
626  // Ensure that the server property of the socket is correctly set.
627  // See https://github.com/nodejs/node/issues/13435
628  socket.server = server;
629
630  // If the user has added a listener to the server,
631  // request, or response, then it's their responsibility.
632  // otherwise, destroy on timeout by default
633  if (server.timeout && typeof socket.setTimeout === 'function')
634    socket.setTimeout(server.timeout);
635  socket.on('timeout', socketOnTimeout);
636
637  const parser = parsers.alloc();
638
639  const lenient = server.insecureHTTPParser === undefined ?
640    isLenient() : server.insecureHTTPParser;
641
642  // TODO(addaleax): This doesn't play well with the
643  // `async_hooks.currentResource()` proposal, see
644  // https://github.com/nodejs/node/pull/21313
645  parser.initialize(
646    HTTPParser.REQUEST,
647    new HTTPServerAsyncResource('HTTPINCOMINGMESSAGE', socket),
648    server.maxHeaderSize || 0,
649    lenient ? kLenientAll : kLenientNone,
650    server[kConnections],
651  );
652  parser.socket = socket;
653  socket.parser = parser;
654
655  // Propagate headers limit from server instance to parser
656  if (typeof server.maxHeadersCount === 'number') {
657    parser.maxHeaderPairs = server.maxHeadersCount << 1;
658  }
659
660  const state = {
661    onData: null,
662    onEnd: null,
663    onClose: null,
664    onDrain: null,
665    outgoing: [],
666    incoming: [],
667    // `outgoingData` is an approximate amount of bytes queued through all
668    // inactive responses. If more data than the high watermark is queued - we
669    // need to pause TCP socket/HTTP parser, and wait until the data will be
670    // sent to the client.
671    outgoingData: 0,
672    requestsCount: 0,
673    keepAliveTimeoutSet: false,
674  };
675  state.onData = socketOnData.bind(undefined,
676                                   server, socket, parser, state);
677  state.onEnd = socketOnEnd.bind(undefined,
678                                 server, socket, parser, state);
679  state.onClose = socketOnClose.bind(undefined,
680                                     socket, state);
681  state.onDrain = socketOnDrain.bind(undefined,
682                                     socket, state);
683  socket.on('data', state.onData);
684  socket.on('error', socketOnError);
685  socket.on('end', state.onEnd);
686  socket.on('close', state.onClose);
687  socket.on('drain', state.onDrain);
688  parser.onIncoming = parserOnIncoming.bind(undefined,
689                                            server, socket, state);
690
691  // We are consuming socket, so it won't get any actual data
692  socket.on('resume', onSocketResume);
693  socket.on('pause', onSocketPause);
694
695  // Overrides to unconsume on `data`, `readable` listeners
696  socket.on = generateSocketListenerWrapper('on');
697  socket.addListener = generateSocketListenerWrapper('addListener');
698  socket.prependListener = generateSocketListenerWrapper('prependListener');
699  socket.setEncoding = socketSetEncoding;
700
701  // We only consume the socket if it has never been consumed before.
702  if (socket._handle && socket._handle.isStreamBase &&
703      !socket._handle._consumed) {
704    parser._consumed = true;
705    socket._handle._consumed = true;
706    parser.consume(socket._handle);
707  }
708  parser[kOnExecute] =
709    onParserExecute.bind(undefined,
710                         server, socket, parser, state);
711
712  parser[kOnTimeout] =
713    onParserTimeout.bind(undefined,
714                         server, socket);
715
716  socket._paused = false;
717}
718
719function socketSetEncoding() {
720  throw new ERR_HTTP_SOCKET_ENCODING();
721}
722
723function updateOutgoingData(socket, state, delta) {
724  state.outgoingData += delta;
725  socketOnDrain(socket, state);
726}
727
728function socketOnDrain(socket, state) {
729  const needPause = state.outgoingData > socket.writableHighWaterMark;
730
731  // If we previously paused, then start reading again.
732  if (socket._paused && !needPause) {
733    socket._paused = false;
734    if (socket.parser)
735      socket.parser.resume();
736    socket.resume();
737  }
738
739  const msg = socket._httpMessage;
740  if (msg && !msg.finished && msg[kNeedDrain]) {
741    msg[kNeedDrain] = false;
742    msg.emit('drain');
743  }
744}
745
746function socketOnTimeout() {
747  const req = this.parser && this.parser.incoming;
748  const reqTimeout = req && !req.complete && req.emit('timeout', this);
749  const res = this._httpMessage;
750  const resTimeout = res && res.emit('timeout', this);
751  const serverTimeout = this.server.emit('timeout', this);
752
753  if (!reqTimeout && !resTimeout && !serverTimeout)
754    this.destroy();
755}
756
757function socketOnClose(socket, state) {
758  debug('server socket close');
759  freeParser(socket.parser, null, socket);
760  abortIncoming(state.incoming);
761}
762
763function abortIncoming(incoming) {
764  while (incoming.length) {
765    const req = incoming.shift();
766    req.destroy(connResetException('aborted'));
767  }
768  // Abort socket._httpMessage ?
769}
770
771function socketOnEnd(server, socket, parser, state) {
772  const ret = parser.finish();
773
774  if (ret instanceof Error) {
775    debug('parse error');
776    // socketOnError has additional logic and will call socket.destroy(err).
777    socketOnError.call(socket, ret);
778  } else if (!server.httpAllowHalfOpen) {
779    socket.end();
780  } else if (state.outgoing.length) {
781    state.outgoing[state.outgoing.length - 1]._last = true;
782  } else if (socket._httpMessage) {
783    socket._httpMessage._last = true;
784  } else {
785    socket.end();
786  }
787}
788
789function socketOnData(server, socket, parser, state, d) {
790  assert(!socket._paused);
791  debug('SERVER socketOnData %d', d.length);
792
793  const ret = parser.execute(d);
794  onParserExecuteCommon(server, socket, parser, state, ret, d);
795}
796
797function onRequestTimeout(socket) {
798  // socketOnError has additional logic and will call socket.destroy(err).
799  socketOnError.call(socket, new ERR_HTTP_REQUEST_TIMEOUT());
800}
801
802function onParserExecute(server, socket, parser, state, ret) {
803  // When underlying `net.Socket` instance is consumed - no
804  // `data` events are emitted, and thus `socket.setTimeout` fires the
805  // callback even if the data is constantly flowing into the socket.
806  // See, https://github.com/nodejs/node/commit/ec2822adaad76b126b5cccdeaa1addf2376c9aa6
807  socket._unrefTimer();
808  debug('SERVER socketOnParserExecute %d', ret);
809  onParserExecuteCommon(server, socket, parser, state, ret, undefined);
810}
811
812function onParserTimeout(server, socket) {
813  const serverTimeout = server.emit('timeout', socket);
814
815  if (!serverTimeout)
816    socket.destroy();
817}
818
819const noop = () => {};
820const badRequestResponse = Buffer.from(
821  `HTTP/1.1 400 ${STATUS_CODES[400]}\r\n` +
822  'Connection: close\r\n\r\n', 'ascii',
823);
824const requestTimeoutResponse = Buffer.from(
825  `HTTP/1.1 408 ${STATUS_CODES[408]}\r\n` +
826  'Connection: close\r\n\r\n', 'ascii',
827);
828const requestHeaderFieldsTooLargeResponse = Buffer.from(
829  `HTTP/1.1 431 ${STATUS_CODES[431]}\r\n` +
830  'Connection: close\r\n\r\n', 'ascii',
831);
832
833function warnUnclosedSocket() {
834  if (warnUnclosedSocket.emitted) {
835    return;
836  }
837
838  warnUnclosedSocket.emitted = true;
839  process.emitWarning(
840    'An error event has already been emitted on the socket. ' +
841    'Please use the destroy method on the socket while handling ' +
842    "a 'clientError' event.",
843  );
844}
845
846function socketOnError(e) {
847  // Ignore further errors
848  this.removeListener('error', socketOnError);
849
850  if (this.listenerCount('error', noop) === 0) {
851    this.on('error', noop);
852  } else {
853    warnUnclosedSocket();
854  }
855
856  if (!this.server.emit('clientError', e, this)) {
857    // Caution must be taken to avoid corrupting the remote peer.
858    // Reply an error segment if there is no in-flight `ServerResponse`,
859    // or no data of the in-flight one has been written yet to this socket.
860    if (this.writable &&
861        (!this._httpMessage || !this._httpMessage._headerSent)) {
862      let response;
863
864      switch (e.code) {
865        case 'HPE_HEADER_OVERFLOW':
866          response = requestHeaderFieldsTooLargeResponse;
867          break;
868        case 'ERR_HTTP_REQUEST_TIMEOUT':
869          response = requestTimeoutResponse;
870          break;
871        default:
872          response = badRequestResponse;
873          break;
874      }
875
876      this.write(response);
877    }
878    this.destroy(e);
879  }
880}
881
882function onParserExecuteCommon(server, socket, parser, state, ret, d) {
883  resetSocketTimeout(server, socket, state);
884
885  if (ret instanceof Error) {
886    prepareError(ret, parser, d);
887    debug('parse error', ret);
888    socketOnError.call(socket, ret);
889  } else if (parser.incoming && parser.incoming.upgrade) {
890    // Upgrade or CONNECT
891    const req = parser.incoming;
892    debug('SERVER upgrade or connect', req.method);
893
894    if (!d)
895      d = parser.getCurrentBuffer();
896
897    socket.removeListener('data', state.onData);
898    socket.removeListener('end', state.onEnd);
899    socket.removeListener('close', state.onClose);
900    socket.removeListener('drain', state.onDrain);
901    socket.removeListener('error', socketOnError);
902    socket.removeListener('timeout', socketOnTimeout);
903    unconsume(parser, socket);
904    parser.finish();
905    freeParser(parser, req, socket);
906    parser = null;
907
908    const eventName = req.method === 'CONNECT' ? 'connect' : 'upgrade';
909    if (eventName === 'upgrade' || server.listenerCount(eventName) > 0) {
910      debug('SERVER have listener for %s', eventName);
911      const bodyHead = d.slice(ret, d.length);
912
913      socket.readableFlowing = null;
914
915      server.emit(eventName, req, socket, bodyHead);
916    } else {
917      // Got CONNECT method, but have no handler.
918      socket.destroy();
919    }
920  } else if (parser.incoming && parser.incoming.method === 'PRI') {
921    debug('SERVER got PRI request');
922    socket.destroy();
923  }
924
925  if (socket._paused && socket.parser) {
926    // onIncoming paused the socket, we should pause the parser as well
927    debug('pause parser');
928    socket.parser.pause();
929  }
930}
931
932function clearIncoming(req) {
933  req = req || this;
934  const parser = req.socket && req.socket.parser;
935  // Reset the .incoming property so that the request object can be gc'ed.
936  if (parser && parser.incoming === req) {
937    if (req.readableEnded) {
938      parser.incoming = null;
939    } else {
940      req.on('end', clearIncoming);
941    }
942  }
943}
944
945function resOnFinish(req, res, socket, state, server) {
946  if (onResponseFinishChannel.hasSubscribers) {
947    onResponseFinishChannel.publish({
948      request: req,
949      response: res,
950      socket,
951      server,
952    });
953  }
954
955  // Usually the first incoming element should be our request.  it may
956  // be that in the case abortIncoming() was called that the incoming
957  // array will be empty.
958  assert(state.incoming.length === 0 || state.incoming[0] === req);
959
960  state.incoming.shift();
961
962  // If the user never called req.read(), and didn't pipe() or
963  // .resume() or .on('data'), then we call req._dump() so that the
964  // bytes will be pulled off the wire.
965  if (!req._consuming && !req._readableState.resumeScheduled)
966    req._dump();
967
968  res.detachSocket(socket);
969  clearIncoming(req);
970  process.nextTick(emitCloseNT, res);
971
972  if (res._last) {
973    if (typeof socket.destroySoon === 'function') {
974      socket.destroySoon();
975    } else {
976      socket.end();
977    }
978  } else if (state.outgoing.length === 0) {
979    if (server.keepAliveTimeout && typeof socket.setTimeout === 'function') {
980      socket.setTimeout(server.keepAliveTimeout);
981      state.keepAliveTimeoutSet = true;
982    }
983  } else {
984    // Start sending the next message
985    const m = state.outgoing.shift();
986    if (m) {
987      m.assignSocket(socket);
988    }
989  }
990}
991
992function emitCloseNT(self) {
993  if (!self._closed) {
994    self.destroyed = true;
995    self._closed = true;
996    self.emit('close');
997  }
998}
999
1000// The following callback is issued after the headers have been read on a
1001// new message. In this callback we setup the response object and pass it
1002// to the user.
1003function parserOnIncoming(server, socket, state, req, keepAlive) {
1004  resetSocketTimeout(server, socket, state);
1005
1006  if (req.upgrade) {
1007    req.upgrade = req.method === 'CONNECT' ||
1008                  server.listenerCount('upgrade') > 0;
1009    if (req.upgrade)
1010      return 2;
1011  }
1012
1013  state.incoming.push(req);
1014
1015  // If the writable end isn't consuming, then stop reading
1016  // so that we don't become overwhelmed by a flood of
1017  // pipelined requests that may never be resolved.
1018  if (!socket._paused) {
1019    const ws = socket._writableState;
1020    if (ws.needDrain || state.outgoingData >= socket.writableHighWaterMark) {
1021      socket._paused = true;
1022      // We also need to pause the parser, but don't do that until after
1023      // the call to execute, because we may still be processing the last
1024      // chunk.
1025      socket.pause();
1026    }
1027  }
1028
1029  const res = new server[kServerResponse](req,
1030                                          {
1031                                            highWaterMark: socket.writableHighWaterMark,
1032                                            rejectNonStandardBodyWrites: server.rejectNonStandardBodyWrites,
1033                                          });
1034  res._keepAliveTimeout = server.keepAliveTimeout;
1035  res._maxRequestsPerSocket = server.maxRequestsPerSocket;
1036  res._onPendingData = updateOutgoingData.bind(undefined,
1037                                               socket, state);
1038
1039  res.shouldKeepAlive = keepAlive;
1040  res[kUniqueHeaders] = server[kUniqueHeaders];
1041  DTRACE_HTTP_SERVER_REQUEST(req, socket);
1042
1043  if (onRequestStartChannel.hasSubscribers) {
1044    onRequestStartChannel.publish({
1045      request: req,
1046      response: res,
1047      socket,
1048      server,
1049    });
1050  }
1051
1052  if (socket._httpMessage) {
1053    // There are already pending outgoing res, append.
1054    state.outgoing.push(res);
1055  } else {
1056    res.assignSocket(socket);
1057  }
1058
1059  // When we're finished writing the response, check if this is the last
1060  // response, if so destroy the socket.
1061  res.on('finish',
1062         resOnFinish.bind(undefined,
1063                          req, res, socket, state, server));
1064
1065  let handled = false;
1066
1067  if (req.httpVersionMajor === 1 && req.httpVersionMinor === 1) {
1068    const isRequestsLimitSet = (
1069      typeof server.maxRequestsPerSocket === 'number' &&
1070      server.maxRequestsPerSocket > 0
1071    );
1072
1073    if (isRequestsLimitSet) {
1074      state.requestsCount++;
1075      res.maxRequestsOnConnectionReached = (
1076        server.maxRequestsPerSocket <= state.requestsCount);
1077    }
1078
1079    if (isRequestsLimitSet &&
1080      (server.maxRequestsPerSocket < state.requestsCount)) {
1081      handled = true;
1082      server.emit('dropRequest', req, socket);
1083      res.writeHead(503);
1084      res.end();
1085    } else if (req.headers.expect !== undefined) {
1086      handled = true;
1087
1088      if (RegExpPrototypeExec(continueExpression, req.headers.expect) !== null) {
1089        res._expect_continue = true;
1090
1091        if (server.listenerCount('checkContinue') > 0) {
1092          server.emit('checkContinue', req, res);
1093        } else {
1094          res.writeContinue();
1095          server.emit('request', req, res);
1096        }
1097      } else if (server.listenerCount('checkExpectation') > 0) {
1098        server.emit('checkExpectation', req, res);
1099      } else {
1100        res.writeHead(417);
1101        res.end();
1102      }
1103    }
1104  }
1105
1106  if (!handled) {
1107    server.emit('request', req, res);
1108  }
1109
1110  return 0;  // No special treatment.
1111}
1112
1113function resetSocketTimeout(server, socket, state) {
1114  if (!state.keepAliveTimeoutSet)
1115    return;
1116
1117  socket.setTimeout(server.timeout || 0);
1118  state.keepAliveTimeoutSet = false;
1119}
1120
1121function onSocketResume() {
1122  // It may seem that the socket is resumed, but this is an enemy's trick to
1123  // deceive us! `resume` is emitted asynchronously, and may be called from
1124  // `incoming.readStart()`. Stop the socket again here, just to preserve the
1125  // state.
1126  //
1127  // We don't care about stream semantics for the consumed socket anyway.
1128  if (this._paused) {
1129    this.pause();
1130    return;
1131  }
1132
1133  if (this._handle && !this._handle.reading) {
1134    this._handle.reading = true;
1135    this._handle.readStart();
1136  }
1137}
1138
1139function onSocketPause() {
1140  if (this._handle && this._handle.reading) {
1141    this._handle.reading = false;
1142    this._handle.readStop();
1143  }
1144}
1145
1146function unconsume(parser, socket) {
1147  if (socket._handle) {
1148    if (parser._consumed)
1149      parser.unconsume();
1150    parser._consumed = false;
1151    socket.removeListener('pause', onSocketPause);
1152    socket.removeListener('resume', onSocketResume);
1153  }
1154}
1155
1156function generateSocketListenerWrapper(originalFnName) {
1157  return function socketListenerWrap(ev, fn) {
1158    const res = net.Socket.prototype[originalFnName].call(this,
1159                                                          ev, fn);
1160    if (!this.parser) {
1161      this.on = net.Socket.prototype.on;
1162      this.addListener = net.Socket.prototype.addListener;
1163      this.prependListener = net.Socket.prototype.prependListener;
1164      return res;
1165    }
1166
1167    if (ev === 'data' || ev === 'readable')
1168      unconsume(this.parser, this);
1169
1170    return res;
1171  };
1172}
1173
1174module.exports = {
1175  STATUS_CODES,
1176  Server,
1177  ServerResponse,
1178  setupConnectionsTracking,
1179  storeHTTPOptions,
1180  _connectionListener: connectionListener,
1181  kServerResponse,
1182};
1183