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