11cb0ef41Sopenharmony_ci// Copyright Joyent, Inc. and other Node contributors.
21cb0ef41Sopenharmony_ci//
31cb0ef41Sopenharmony_ci// Permission is hereby granted, free of charge, to any person obtaining a
41cb0ef41Sopenharmony_ci// copy of this software and associated documentation files (the
51cb0ef41Sopenharmony_ci// "Software"), to deal in the Software without restriction, including
61cb0ef41Sopenharmony_ci// without limitation the rights to use, copy, modify, merge, publish,
71cb0ef41Sopenharmony_ci// distribute, sublicense, and/or sell copies of the Software, and to permit
81cb0ef41Sopenharmony_ci// persons to whom the Software is furnished to do so, subject to the
91cb0ef41Sopenharmony_ci// following conditions:
101cb0ef41Sopenharmony_ci//
111cb0ef41Sopenharmony_ci// The above copyright notice and this permission notice shall be included
121cb0ef41Sopenharmony_ci// in all copies or substantial portions of the Software.
131cb0ef41Sopenharmony_ci//
141cb0ef41Sopenharmony_ci// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
151cb0ef41Sopenharmony_ci// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
161cb0ef41Sopenharmony_ci// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
171cb0ef41Sopenharmony_ci// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
181cb0ef41Sopenharmony_ci// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
191cb0ef41Sopenharmony_ci// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
201cb0ef41Sopenharmony_ci// USE OR OTHER DEALINGS IN THE SOFTWARE.
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ci'use strict';
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_ciconst {
251cb0ef41Sopenharmony_ci  ArrayIsArray,
261cb0ef41Sopenharmony_ci  Boolean,
271cb0ef41Sopenharmony_ci  Error,
281cb0ef41Sopenharmony_ci  FunctionPrototypeCall,
291cb0ef41Sopenharmony_ci  NumberIsFinite,
301cb0ef41Sopenharmony_ci  ObjectAssign,
311cb0ef41Sopenharmony_ci  ObjectKeys,
321cb0ef41Sopenharmony_ci  ObjectSetPrototypeOf,
331cb0ef41Sopenharmony_ci  ReflectApply,
341cb0ef41Sopenharmony_ci  RegExpPrototypeExec,
351cb0ef41Sopenharmony_ci  String,
361cb0ef41Sopenharmony_ci  StringPrototypeCharCodeAt,
371cb0ef41Sopenharmony_ci  StringPrototypeIncludes,
381cb0ef41Sopenharmony_ci  StringPrototypeIndexOf,
391cb0ef41Sopenharmony_ci  StringPrototypeToUpperCase,
401cb0ef41Sopenharmony_ci  Symbol,
411cb0ef41Sopenharmony_ci  TypedArrayPrototypeSlice,
421cb0ef41Sopenharmony_ci} = primordials;
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ciconst net = require('net');
451cb0ef41Sopenharmony_ciconst assert = require('internal/assert');
461cb0ef41Sopenharmony_ciconst {
471cb0ef41Sopenharmony_ci  kEmptyObject,
481cb0ef41Sopenharmony_ci  once,
491cb0ef41Sopenharmony_ci} = require('internal/util');
501cb0ef41Sopenharmony_ciconst {
511cb0ef41Sopenharmony_ci  _checkIsHttpToken: checkIsHttpToken,
521cb0ef41Sopenharmony_ci  freeParser,
531cb0ef41Sopenharmony_ci  parsers,
541cb0ef41Sopenharmony_ci  HTTPParser,
551cb0ef41Sopenharmony_ci  isLenient,
561cb0ef41Sopenharmony_ci  prepareError,
571cb0ef41Sopenharmony_ci} = require('_http_common');
581cb0ef41Sopenharmony_ciconst {
591cb0ef41Sopenharmony_ci  kUniqueHeaders,
601cb0ef41Sopenharmony_ci  parseUniqueHeadersOption,
611cb0ef41Sopenharmony_ci  OutgoingMessage,
621cb0ef41Sopenharmony_ci} = require('_http_outgoing');
631cb0ef41Sopenharmony_ciconst Agent = require('_http_agent');
641cb0ef41Sopenharmony_ciconst { Buffer } = require('buffer');
651cb0ef41Sopenharmony_ciconst { defaultTriggerAsyncIdScope } = require('internal/async_hooks');
661cb0ef41Sopenharmony_ciconst { URL, urlToHttpOptions, isURL } = require('internal/url');
671cb0ef41Sopenharmony_ciconst {
681cb0ef41Sopenharmony_ci  kOutHeaders,
691cb0ef41Sopenharmony_ci  kNeedDrain,
701cb0ef41Sopenharmony_ci  isTraceHTTPEnabled,
711cb0ef41Sopenharmony_ci  traceBegin,
721cb0ef41Sopenharmony_ci  traceEnd,
731cb0ef41Sopenharmony_ci  getNextTraceEventId,
741cb0ef41Sopenharmony_ci} = require('internal/http');
751cb0ef41Sopenharmony_ciconst { connResetException, codes } = require('internal/errors');
761cb0ef41Sopenharmony_ciconst {
771cb0ef41Sopenharmony_ci  ERR_HTTP_HEADERS_SENT,
781cb0ef41Sopenharmony_ci  ERR_INVALID_ARG_TYPE,
791cb0ef41Sopenharmony_ci  ERR_INVALID_HTTP_TOKEN,
801cb0ef41Sopenharmony_ci  ERR_INVALID_PROTOCOL,
811cb0ef41Sopenharmony_ci  ERR_UNESCAPED_CHARACTERS,
821cb0ef41Sopenharmony_ci} = codes;
831cb0ef41Sopenharmony_ciconst {
841cb0ef41Sopenharmony_ci  validateInteger,
851cb0ef41Sopenharmony_ci  validateBoolean,
861cb0ef41Sopenharmony_ci} = require('internal/validators');
871cb0ef41Sopenharmony_ciconst { getTimerDuration } = require('internal/timers');
881cb0ef41Sopenharmony_ciconst {
891cb0ef41Sopenharmony_ci  DTRACE_HTTP_CLIENT_REQUEST,
901cb0ef41Sopenharmony_ci  DTRACE_HTTP_CLIENT_RESPONSE,
911cb0ef41Sopenharmony_ci} = require('internal/dtrace');
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ciconst {
941cb0ef41Sopenharmony_ci  hasObserver,
951cb0ef41Sopenharmony_ci  startPerf,
961cb0ef41Sopenharmony_ci  stopPerf,
971cb0ef41Sopenharmony_ci} = require('internal/perf/observe');
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_ciconst kClientRequestStatistics = Symbol('ClientRequestStatistics');
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ciconst dc = require('diagnostics_channel');
1021cb0ef41Sopenharmony_ciconst onClientRequestStartChannel = dc.channel('http.client.request.start');
1031cb0ef41Sopenharmony_ciconst onClientResponseFinishChannel = dc.channel('http.client.response.finish');
1041cb0ef41Sopenharmony_ci
1051cb0ef41Sopenharmony_ciconst { addAbortSignal, finished } = require('stream');
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_cilet debug = require('internal/util/debuglog').debuglog('http', (fn) => {
1081cb0ef41Sopenharmony_ci  debug = fn;
1091cb0ef41Sopenharmony_ci});
1101cb0ef41Sopenharmony_ci
1111cb0ef41Sopenharmony_ciconst INVALID_PATH_REGEX = /[^\u0021-\u00ff]/;
1121cb0ef41Sopenharmony_ciconst kError = Symbol('kError');
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_ciconst kLenientAll = HTTPParser.kLenientAll | 0;
1151cb0ef41Sopenharmony_ciconst kLenientNone = HTTPParser.kLenientNone | 0;
1161cb0ef41Sopenharmony_ci
1171cb0ef41Sopenharmony_ciconst HTTP_CLIENT_TRACE_EVENT_NAME = 'http.client.request';
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_cifunction validateHost(host, name) {
1201cb0ef41Sopenharmony_ci  if (host !== null && host !== undefined && typeof host !== 'string') {
1211cb0ef41Sopenharmony_ci    throw new ERR_INVALID_ARG_TYPE(`options.${name}`,
1221cb0ef41Sopenharmony_ci                                   ['string', 'undefined', 'null'],
1231cb0ef41Sopenharmony_ci                                   host);
1241cb0ef41Sopenharmony_ci  }
1251cb0ef41Sopenharmony_ci  return host;
1261cb0ef41Sopenharmony_ci}
1271cb0ef41Sopenharmony_ci
1281cb0ef41Sopenharmony_ciclass HTTPClientAsyncResource {
1291cb0ef41Sopenharmony_ci  constructor(type, req) {
1301cb0ef41Sopenharmony_ci    this.type = type;
1311cb0ef41Sopenharmony_ci    this.req = req;
1321cb0ef41Sopenharmony_ci  }
1331cb0ef41Sopenharmony_ci}
1341cb0ef41Sopenharmony_ci
1351cb0ef41Sopenharmony_cifunction ClientRequest(input, options, cb) {
1361cb0ef41Sopenharmony_ci  FunctionPrototypeCall(OutgoingMessage, this);
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_ci  if (typeof input === 'string') {
1391cb0ef41Sopenharmony_ci    const urlStr = input;
1401cb0ef41Sopenharmony_ci    input = urlToHttpOptions(new URL(urlStr));
1411cb0ef41Sopenharmony_ci  } else if (isURL(input)) {
1421cb0ef41Sopenharmony_ci    // url.URL instance
1431cb0ef41Sopenharmony_ci    input = urlToHttpOptions(input);
1441cb0ef41Sopenharmony_ci  } else {
1451cb0ef41Sopenharmony_ci    cb = options;
1461cb0ef41Sopenharmony_ci    options = input;
1471cb0ef41Sopenharmony_ci    input = null;
1481cb0ef41Sopenharmony_ci  }
1491cb0ef41Sopenharmony_ci
1501cb0ef41Sopenharmony_ci  if (typeof options === 'function') {
1511cb0ef41Sopenharmony_ci    cb = options;
1521cb0ef41Sopenharmony_ci    options = input || kEmptyObject;
1531cb0ef41Sopenharmony_ci  } else {
1541cb0ef41Sopenharmony_ci    options = ObjectAssign(input || {}, options);
1551cb0ef41Sopenharmony_ci  }
1561cb0ef41Sopenharmony_ci
1571cb0ef41Sopenharmony_ci  let agent = options.agent;
1581cb0ef41Sopenharmony_ci  const defaultAgent = options._defaultAgent || Agent.globalAgent;
1591cb0ef41Sopenharmony_ci  if (agent === false) {
1601cb0ef41Sopenharmony_ci    agent = new defaultAgent.constructor();
1611cb0ef41Sopenharmony_ci  } else if (agent === null || agent === undefined) {
1621cb0ef41Sopenharmony_ci    if (typeof options.createConnection !== 'function') {
1631cb0ef41Sopenharmony_ci      agent = defaultAgent;
1641cb0ef41Sopenharmony_ci    }
1651cb0ef41Sopenharmony_ci    // Explicitly pass through this statement as agent will not be used
1661cb0ef41Sopenharmony_ci    // when createConnection is provided.
1671cb0ef41Sopenharmony_ci  } else if (typeof agent.addRequest !== 'function') {
1681cb0ef41Sopenharmony_ci    throw new ERR_INVALID_ARG_TYPE('options.agent',
1691cb0ef41Sopenharmony_ci                                   ['Agent-like Object', 'undefined', 'false'],
1701cb0ef41Sopenharmony_ci                                   agent);
1711cb0ef41Sopenharmony_ci  }
1721cb0ef41Sopenharmony_ci  this.agent = agent;
1731cb0ef41Sopenharmony_ci
1741cb0ef41Sopenharmony_ci  const protocol = options.protocol || defaultAgent.protocol;
1751cb0ef41Sopenharmony_ci  let expectedProtocol = defaultAgent.protocol;
1761cb0ef41Sopenharmony_ci  if (this.agent && this.agent.protocol)
1771cb0ef41Sopenharmony_ci    expectedProtocol = this.agent.protocol;
1781cb0ef41Sopenharmony_ci
1791cb0ef41Sopenharmony_ci  if (options.path) {
1801cb0ef41Sopenharmony_ci    const path = String(options.path);
1811cb0ef41Sopenharmony_ci    if (RegExpPrototypeExec(INVALID_PATH_REGEX, path) !== null) {
1821cb0ef41Sopenharmony_ci      debug('Path contains unescaped characters: "%s"', path);
1831cb0ef41Sopenharmony_ci      throw new ERR_UNESCAPED_CHARACTERS('Request path');
1841cb0ef41Sopenharmony_ci    }
1851cb0ef41Sopenharmony_ci  }
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ci  if (protocol !== expectedProtocol) {
1881cb0ef41Sopenharmony_ci    throw new ERR_INVALID_PROTOCOL(protocol, expectedProtocol);
1891cb0ef41Sopenharmony_ci  }
1901cb0ef41Sopenharmony_ci
1911cb0ef41Sopenharmony_ci  const defaultPort = options.defaultPort ||
1921cb0ef41Sopenharmony_ci                    (this.agent && this.agent.defaultPort);
1931cb0ef41Sopenharmony_ci
1941cb0ef41Sopenharmony_ci  const port = options.port = options.port || defaultPort || 80;
1951cb0ef41Sopenharmony_ci  const host = options.host = validateHost(options.hostname, 'hostname') ||
1961cb0ef41Sopenharmony_ci                            validateHost(options.host, 'host') || 'localhost';
1971cb0ef41Sopenharmony_ci
1981cb0ef41Sopenharmony_ci  const setHost = (options.setHost === undefined || Boolean(options.setHost));
1991cb0ef41Sopenharmony_ci
2001cb0ef41Sopenharmony_ci  this.socketPath = options.socketPath;
2011cb0ef41Sopenharmony_ci
2021cb0ef41Sopenharmony_ci  if (options.timeout !== undefined)
2031cb0ef41Sopenharmony_ci    this.timeout = getTimerDuration(options.timeout, 'timeout');
2041cb0ef41Sopenharmony_ci
2051cb0ef41Sopenharmony_ci  const signal = options.signal;
2061cb0ef41Sopenharmony_ci  if (signal) {
2071cb0ef41Sopenharmony_ci    addAbortSignal(signal, this);
2081cb0ef41Sopenharmony_ci  }
2091cb0ef41Sopenharmony_ci  let method = options.method;
2101cb0ef41Sopenharmony_ci  const methodIsString = (typeof method === 'string');
2111cb0ef41Sopenharmony_ci  if (method !== null && method !== undefined && !methodIsString) {
2121cb0ef41Sopenharmony_ci    throw new ERR_INVALID_ARG_TYPE('options.method', 'string', method);
2131cb0ef41Sopenharmony_ci  }
2141cb0ef41Sopenharmony_ci
2151cb0ef41Sopenharmony_ci  if (methodIsString && method) {
2161cb0ef41Sopenharmony_ci    if (!checkIsHttpToken(method)) {
2171cb0ef41Sopenharmony_ci      throw new ERR_INVALID_HTTP_TOKEN('Method', method);
2181cb0ef41Sopenharmony_ci    }
2191cb0ef41Sopenharmony_ci    method = this.method = StringPrototypeToUpperCase(method);
2201cb0ef41Sopenharmony_ci  } else {
2211cb0ef41Sopenharmony_ci    method = this.method = 'GET';
2221cb0ef41Sopenharmony_ci  }
2231cb0ef41Sopenharmony_ci
2241cb0ef41Sopenharmony_ci  const maxHeaderSize = options.maxHeaderSize;
2251cb0ef41Sopenharmony_ci  if (maxHeaderSize !== undefined)
2261cb0ef41Sopenharmony_ci    validateInteger(maxHeaderSize, 'maxHeaderSize', 0);
2271cb0ef41Sopenharmony_ci  this.maxHeaderSize = maxHeaderSize;
2281cb0ef41Sopenharmony_ci
2291cb0ef41Sopenharmony_ci  const insecureHTTPParser = options.insecureHTTPParser;
2301cb0ef41Sopenharmony_ci  if (insecureHTTPParser !== undefined) {
2311cb0ef41Sopenharmony_ci    validateBoolean(insecureHTTPParser, 'options.insecureHTTPParser');
2321cb0ef41Sopenharmony_ci  }
2331cb0ef41Sopenharmony_ci
2341cb0ef41Sopenharmony_ci  this.insecureHTTPParser = insecureHTTPParser;
2351cb0ef41Sopenharmony_ci
2361cb0ef41Sopenharmony_ci  if (options.joinDuplicateHeaders !== undefined) {
2371cb0ef41Sopenharmony_ci    validateBoolean(options.joinDuplicateHeaders, 'options.joinDuplicateHeaders');
2381cb0ef41Sopenharmony_ci  }
2391cb0ef41Sopenharmony_ci
2401cb0ef41Sopenharmony_ci  this.joinDuplicateHeaders = options.joinDuplicateHeaders;
2411cb0ef41Sopenharmony_ci
2421cb0ef41Sopenharmony_ci  this.path = options.path || '/';
2431cb0ef41Sopenharmony_ci  if (cb) {
2441cb0ef41Sopenharmony_ci    this.once('response', cb);
2451cb0ef41Sopenharmony_ci  }
2461cb0ef41Sopenharmony_ci
2471cb0ef41Sopenharmony_ci  if (method === 'GET' ||
2481cb0ef41Sopenharmony_ci      method === 'HEAD' ||
2491cb0ef41Sopenharmony_ci      method === 'DELETE' ||
2501cb0ef41Sopenharmony_ci      method === 'OPTIONS' ||
2511cb0ef41Sopenharmony_ci      method === 'TRACE' ||
2521cb0ef41Sopenharmony_ci      method === 'CONNECT') {
2531cb0ef41Sopenharmony_ci    this.useChunkedEncodingByDefault = false;
2541cb0ef41Sopenharmony_ci  } else {
2551cb0ef41Sopenharmony_ci    this.useChunkedEncodingByDefault = true;
2561cb0ef41Sopenharmony_ci  }
2571cb0ef41Sopenharmony_ci
2581cb0ef41Sopenharmony_ci  this._ended = false;
2591cb0ef41Sopenharmony_ci  this.res = null;
2601cb0ef41Sopenharmony_ci  this.aborted = false;
2611cb0ef41Sopenharmony_ci  this.timeoutCb = null;
2621cb0ef41Sopenharmony_ci  this.upgradeOrConnect = false;
2631cb0ef41Sopenharmony_ci  this.parser = null;
2641cb0ef41Sopenharmony_ci  this.maxHeadersCount = null;
2651cb0ef41Sopenharmony_ci  this.reusedSocket = false;
2661cb0ef41Sopenharmony_ci  this.host = host;
2671cb0ef41Sopenharmony_ci  this.protocol = protocol;
2681cb0ef41Sopenharmony_ci
2691cb0ef41Sopenharmony_ci  if (this.agent) {
2701cb0ef41Sopenharmony_ci    // If there is an agent we should default to Connection:keep-alive,
2711cb0ef41Sopenharmony_ci    // but only if the Agent will actually reuse the connection!
2721cb0ef41Sopenharmony_ci    // If it's not a keepAlive agent, and the maxSockets==Infinity, then
2731cb0ef41Sopenharmony_ci    // there's never a case where this socket will actually be reused
2741cb0ef41Sopenharmony_ci    if (!this.agent.keepAlive && !NumberIsFinite(this.agent.maxSockets)) {
2751cb0ef41Sopenharmony_ci      this._last = true;
2761cb0ef41Sopenharmony_ci      this.shouldKeepAlive = false;
2771cb0ef41Sopenharmony_ci    } else {
2781cb0ef41Sopenharmony_ci      this._last = false;
2791cb0ef41Sopenharmony_ci      this.shouldKeepAlive = true;
2801cb0ef41Sopenharmony_ci    }
2811cb0ef41Sopenharmony_ci  }
2821cb0ef41Sopenharmony_ci
2831cb0ef41Sopenharmony_ci  const headersArray = ArrayIsArray(options.headers);
2841cb0ef41Sopenharmony_ci  if (!headersArray) {
2851cb0ef41Sopenharmony_ci    if (options.headers) {
2861cb0ef41Sopenharmony_ci      const keys = ObjectKeys(options.headers);
2871cb0ef41Sopenharmony_ci      // Retain for(;;) loop for performance reasons
2881cb0ef41Sopenharmony_ci      // Refs: https://github.com/nodejs/node/pull/30958
2891cb0ef41Sopenharmony_ci      for (let i = 0; i < keys.length; i++) {
2901cb0ef41Sopenharmony_ci        const key = keys[i];
2911cb0ef41Sopenharmony_ci        this.setHeader(key, options.headers[key]);
2921cb0ef41Sopenharmony_ci      }
2931cb0ef41Sopenharmony_ci    }
2941cb0ef41Sopenharmony_ci
2951cb0ef41Sopenharmony_ci    if (host && !this.getHeader('host') && setHost) {
2961cb0ef41Sopenharmony_ci      let hostHeader = host;
2971cb0ef41Sopenharmony_ci
2981cb0ef41Sopenharmony_ci      // For the Host header, ensure that IPv6 addresses are enclosed
2991cb0ef41Sopenharmony_ci      // in square brackets, as defined by URI formatting
3001cb0ef41Sopenharmony_ci      // https://tools.ietf.org/html/rfc3986#section-3.2.2
3011cb0ef41Sopenharmony_ci      const posColon = StringPrototypeIndexOf(hostHeader, ':');
3021cb0ef41Sopenharmony_ci      if (posColon !== -1 &&
3031cb0ef41Sopenharmony_ci          StringPrototypeIncludes(hostHeader, ':', posColon + 1) &&
3041cb0ef41Sopenharmony_ci          StringPrototypeCharCodeAt(hostHeader, 0) !== 91/* '[' */) {
3051cb0ef41Sopenharmony_ci        hostHeader = `[${hostHeader}]`;
3061cb0ef41Sopenharmony_ci      }
3071cb0ef41Sopenharmony_ci
3081cb0ef41Sopenharmony_ci      if (port && +port !== defaultPort) {
3091cb0ef41Sopenharmony_ci        hostHeader += ':' + port;
3101cb0ef41Sopenharmony_ci      }
3111cb0ef41Sopenharmony_ci      this.setHeader('Host', hostHeader);
3121cb0ef41Sopenharmony_ci    }
3131cb0ef41Sopenharmony_ci
3141cb0ef41Sopenharmony_ci    if (options.auth && !this.getHeader('Authorization')) {
3151cb0ef41Sopenharmony_ci      this.setHeader('Authorization', 'Basic ' +
3161cb0ef41Sopenharmony_ci                     Buffer.from(options.auth).toString('base64'));
3171cb0ef41Sopenharmony_ci    }
3181cb0ef41Sopenharmony_ci
3191cb0ef41Sopenharmony_ci    if (this.getHeader('expect')) {
3201cb0ef41Sopenharmony_ci      if (this._header) {
3211cb0ef41Sopenharmony_ci        throw new ERR_HTTP_HEADERS_SENT('render');
3221cb0ef41Sopenharmony_ci      }
3231cb0ef41Sopenharmony_ci
3241cb0ef41Sopenharmony_ci      this._storeHeader(this.method + ' ' + this.path + ' HTTP/1.1\r\n',
3251cb0ef41Sopenharmony_ci                        this[kOutHeaders]);
3261cb0ef41Sopenharmony_ci    }
3271cb0ef41Sopenharmony_ci  } else {
3281cb0ef41Sopenharmony_ci    this._storeHeader(this.method + ' ' + this.path + ' HTTP/1.1\r\n',
3291cb0ef41Sopenharmony_ci                      options.headers);
3301cb0ef41Sopenharmony_ci  }
3311cb0ef41Sopenharmony_ci
3321cb0ef41Sopenharmony_ci  this[kUniqueHeaders] = parseUniqueHeadersOption(options.uniqueHeaders);
3331cb0ef41Sopenharmony_ci
3341cb0ef41Sopenharmony_ci  let optsWithoutSignal = options;
3351cb0ef41Sopenharmony_ci  if (optsWithoutSignal.signal) {
3361cb0ef41Sopenharmony_ci    optsWithoutSignal = ObjectAssign({}, options);
3371cb0ef41Sopenharmony_ci    delete optsWithoutSignal.signal;
3381cb0ef41Sopenharmony_ci  }
3391cb0ef41Sopenharmony_ci
3401cb0ef41Sopenharmony_ci  // initiate connection
3411cb0ef41Sopenharmony_ci  if (this.agent) {
3421cb0ef41Sopenharmony_ci    this.agent.addRequest(this, optsWithoutSignal);
3431cb0ef41Sopenharmony_ci  } else {
3441cb0ef41Sopenharmony_ci    // No agent, default to Connection:close.
3451cb0ef41Sopenharmony_ci    this._last = true;
3461cb0ef41Sopenharmony_ci    this.shouldKeepAlive = false;
3471cb0ef41Sopenharmony_ci    if (typeof optsWithoutSignal.createConnection === 'function') {
3481cb0ef41Sopenharmony_ci      const oncreate = once((err, socket) => {
3491cb0ef41Sopenharmony_ci        if (err) {
3501cb0ef41Sopenharmony_ci          process.nextTick(() => this.emit('error', err));
3511cb0ef41Sopenharmony_ci        } else {
3521cb0ef41Sopenharmony_ci          this.onSocket(socket);
3531cb0ef41Sopenharmony_ci        }
3541cb0ef41Sopenharmony_ci      });
3551cb0ef41Sopenharmony_ci
3561cb0ef41Sopenharmony_ci      try {
3571cb0ef41Sopenharmony_ci        const newSocket = optsWithoutSignal.createConnection(optsWithoutSignal,
3581cb0ef41Sopenharmony_ci                                                             oncreate);
3591cb0ef41Sopenharmony_ci        if (newSocket) {
3601cb0ef41Sopenharmony_ci          oncreate(null, newSocket);
3611cb0ef41Sopenharmony_ci        }
3621cb0ef41Sopenharmony_ci      } catch (err) {
3631cb0ef41Sopenharmony_ci        oncreate(err);
3641cb0ef41Sopenharmony_ci      }
3651cb0ef41Sopenharmony_ci    } else {
3661cb0ef41Sopenharmony_ci      debug('CLIENT use net.createConnection', optsWithoutSignal);
3671cb0ef41Sopenharmony_ci      this.onSocket(net.createConnection(optsWithoutSignal));
3681cb0ef41Sopenharmony_ci    }
3691cb0ef41Sopenharmony_ci  }
3701cb0ef41Sopenharmony_ci}
3711cb0ef41Sopenharmony_ciObjectSetPrototypeOf(ClientRequest.prototype, OutgoingMessage.prototype);
3721cb0ef41Sopenharmony_ciObjectSetPrototypeOf(ClientRequest, OutgoingMessage);
3731cb0ef41Sopenharmony_ci
3741cb0ef41Sopenharmony_ciClientRequest.prototype._finish = function _finish() {
3751cb0ef41Sopenharmony_ci  DTRACE_HTTP_CLIENT_REQUEST(this, this.socket);
3761cb0ef41Sopenharmony_ci  FunctionPrototypeCall(OutgoingMessage.prototype._finish, this);
3771cb0ef41Sopenharmony_ci  if (hasObserver('http')) {
3781cb0ef41Sopenharmony_ci    startPerf(this, kClientRequestStatistics, {
3791cb0ef41Sopenharmony_ci      type: 'http',
3801cb0ef41Sopenharmony_ci      name: 'HttpClient',
3811cb0ef41Sopenharmony_ci      detail: {
3821cb0ef41Sopenharmony_ci        req: {
3831cb0ef41Sopenharmony_ci          method: this.method,
3841cb0ef41Sopenharmony_ci          url: `${this.protocol}//${this.host}${this.path}`,
3851cb0ef41Sopenharmony_ci          headers: typeof this.getHeaders === 'function' ? this.getHeaders() : {},
3861cb0ef41Sopenharmony_ci        },
3871cb0ef41Sopenharmony_ci      },
3881cb0ef41Sopenharmony_ci    });
3891cb0ef41Sopenharmony_ci  }
3901cb0ef41Sopenharmony_ci  if (onClientRequestStartChannel.hasSubscribers) {
3911cb0ef41Sopenharmony_ci    onClientRequestStartChannel.publish({
3921cb0ef41Sopenharmony_ci      request: this,
3931cb0ef41Sopenharmony_ci    });
3941cb0ef41Sopenharmony_ci  }
3951cb0ef41Sopenharmony_ci  if (isTraceHTTPEnabled()) {
3961cb0ef41Sopenharmony_ci    this._traceEventId = getNextTraceEventId();
3971cb0ef41Sopenharmony_ci    traceBegin(HTTP_CLIENT_TRACE_EVENT_NAME, this._traceEventId);
3981cb0ef41Sopenharmony_ci  }
3991cb0ef41Sopenharmony_ci};
4001cb0ef41Sopenharmony_ci
4011cb0ef41Sopenharmony_ciClientRequest.prototype._implicitHeader = function _implicitHeader() {
4021cb0ef41Sopenharmony_ci  if (this._header) {
4031cb0ef41Sopenharmony_ci    throw new ERR_HTTP_HEADERS_SENT('render');
4041cb0ef41Sopenharmony_ci  }
4051cb0ef41Sopenharmony_ci  this._storeHeader(this.method + ' ' + this.path + ' HTTP/1.1\r\n',
4061cb0ef41Sopenharmony_ci                    this[kOutHeaders]);
4071cb0ef41Sopenharmony_ci};
4081cb0ef41Sopenharmony_ci
4091cb0ef41Sopenharmony_ciClientRequest.prototype.abort = function abort() {
4101cb0ef41Sopenharmony_ci  if (this.aborted) {
4111cb0ef41Sopenharmony_ci    return;
4121cb0ef41Sopenharmony_ci  }
4131cb0ef41Sopenharmony_ci  this.aborted = true;
4141cb0ef41Sopenharmony_ci  process.nextTick(emitAbortNT, this);
4151cb0ef41Sopenharmony_ci  this.destroy();
4161cb0ef41Sopenharmony_ci};
4171cb0ef41Sopenharmony_ci
4181cb0ef41Sopenharmony_ciClientRequest.prototype.destroy = function destroy(err) {
4191cb0ef41Sopenharmony_ci  if (this.destroyed) {
4201cb0ef41Sopenharmony_ci    return this;
4211cb0ef41Sopenharmony_ci  }
4221cb0ef41Sopenharmony_ci  this.destroyed = true;
4231cb0ef41Sopenharmony_ci
4241cb0ef41Sopenharmony_ci  // If we're aborting, we don't care about any more response data.
4251cb0ef41Sopenharmony_ci  if (this.res) {
4261cb0ef41Sopenharmony_ci    this.res._dump();
4271cb0ef41Sopenharmony_ci  }
4281cb0ef41Sopenharmony_ci
4291cb0ef41Sopenharmony_ci  this[kError] = err;
4301cb0ef41Sopenharmony_ci  this.socket?.destroy(err);
4311cb0ef41Sopenharmony_ci
4321cb0ef41Sopenharmony_ci  return this;
4331cb0ef41Sopenharmony_ci};
4341cb0ef41Sopenharmony_ci
4351cb0ef41Sopenharmony_cifunction emitAbortNT(req) {
4361cb0ef41Sopenharmony_ci  req.emit('abort');
4371cb0ef41Sopenharmony_ci}
4381cb0ef41Sopenharmony_ci
4391cb0ef41Sopenharmony_cifunction ondrain() {
4401cb0ef41Sopenharmony_ci  const msg = this._httpMessage;
4411cb0ef41Sopenharmony_ci  if (msg && !msg.finished && msg[kNeedDrain]) {
4421cb0ef41Sopenharmony_ci    msg[kNeedDrain] = false;
4431cb0ef41Sopenharmony_ci    msg.emit('drain');
4441cb0ef41Sopenharmony_ci  }
4451cb0ef41Sopenharmony_ci}
4461cb0ef41Sopenharmony_ci
4471cb0ef41Sopenharmony_cifunction socketCloseListener() {
4481cb0ef41Sopenharmony_ci  const socket = this;
4491cb0ef41Sopenharmony_ci  const req = socket._httpMessage;
4501cb0ef41Sopenharmony_ci  debug('HTTP socket close');
4511cb0ef41Sopenharmony_ci
4521cb0ef41Sopenharmony_ci  // NOTE: It's important to get parser here, because it could be freed by
4531cb0ef41Sopenharmony_ci  // the `socketOnData`.
4541cb0ef41Sopenharmony_ci  const parser = socket.parser;
4551cb0ef41Sopenharmony_ci  const res = req.res;
4561cb0ef41Sopenharmony_ci
4571cb0ef41Sopenharmony_ci  req.destroyed = true;
4581cb0ef41Sopenharmony_ci  if (res) {
4591cb0ef41Sopenharmony_ci    // Socket closed before we emitted 'end' below.
4601cb0ef41Sopenharmony_ci    if (!res.complete) {
4611cb0ef41Sopenharmony_ci      res.destroy(connResetException('aborted'));
4621cb0ef41Sopenharmony_ci    }
4631cb0ef41Sopenharmony_ci    req._closed = true;
4641cb0ef41Sopenharmony_ci    req.emit('close');
4651cb0ef41Sopenharmony_ci    if (!res.aborted && res.readable) {
4661cb0ef41Sopenharmony_ci      res.push(null);
4671cb0ef41Sopenharmony_ci    }
4681cb0ef41Sopenharmony_ci  } else {
4691cb0ef41Sopenharmony_ci    if (!req.socket._hadError) {
4701cb0ef41Sopenharmony_ci      // This socket error fired before we started to
4711cb0ef41Sopenharmony_ci      // receive a response. The error needs to
4721cb0ef41Sopenharmony_ci      // fire on the request.
4731cb0ef41Sopenharmony_ci      req.socket._hadError = true;
4741cb0ef41Sopenharmony_ci      req.emit('error', connResetException('socket hang up'));
4751cb0ef41Sopenharmony_ci    }
4761cb0ef41Sopenharmony_ci    req._closed = true;
4771cb0ef41Sopenharmony_ci    req.emit('close');
4781cb0ef41Sopenharmony_ci  }
4791cb0ef41Sopenharmony_ci
4801cb0ef41Sopenharmony_ci  // Too bad.  That output wasn't getting written.
4811cb0ef41Sopenharmony_ci  // This is pretty terrible that it doesn't raise an error.
4821cb0ef41Sopenharmony_ci  // Fixed better in v0.10
4831cb0ef41Sopenharmony_ci  if (req.outputData)
4841cb0ef41Sopenharmony_ci    req.outputData.length = 0;
4851cb0ef41Sopenharmony_ci
4861cb0ef41Sopenharmony_ci  if (parser) {
4871cb0ef41Sopenharmony_ci    parser.finish();
4881cb0ef41Sopenharmony_ci    freeParser(parser, req, socket);
4891cb0ef41Sopenharmony_ci  }
4901cb0ef41Sopenharmony_ci}
4911cb0ef41Sopenharmony_ci
4921cb0ef41Sopenharmony_cifunction socketErrorListener(err) {
4931cb0ef41Sopenharmony_ci  const socket = this;
4941cb0ef41Sopenharmony_ci  const req = socket._httpMessage;
4951cb0ef41Sopenharmony_ci  debug('SOCKET ERROR:', err.message, err.stack);
4961cb0ef41Sopenharmony_ci
4971cb0ef41Sopenharmony_ci  if (req) {
4981cb0ef41Sopenharmony_ci    // For Safety. Some additional errors might fire later on
4991cb0ef41Sopenharmony_ci    // and we need to make sure we don't double-fire the error event.
5001cb0ef41Sopenharmony_ci    req.socket._hadError = true;
5011cb0ef41Sopenharmony_ci    req.emit('error', err);
5021cb0ef41Sopenharmony_ci  }
5031cb0ef41Sopenharmony_ci
5041cb0ef41Sopenharmony_ci  const parser = socket.parser;
5051cb0ef41Sopenharmony_ci  if (parser) {
5061cb0ef41Sopenharmony_ci    parser.finish();
5071cb0ef41Sopenharmony_ci    freeParser(parser, req, socket);
5081cb0ef41Sopenharmony_ci  }
5091cb0ef41Sopenharmony_ci
5101cb0ef41Sopenharmony_ci  // Ensure that no further data will come out of the socket
5111cb0ef41Sopenharmony_ci  socket.removeListener('data', socketOnData);
5121cb0ef41Sopenharmony_ci  socket.removeListener('end', socketOnEnd);
5131cb0ef41Sopenharmony_ci  socket.destroy();
5141cb0ef41Sopenharmony_ci}
5151cb0ef41Sopenharmony_ci
5161cb0ef41Sopenharmony_cifunction socketOnEnd() {
5171cb0ef41Sopenharmony_ci  const socket = this;
5181cb0ef41Sopenharmony_ci  const req = this._httpMessage;
5191cb0ef41Sopenharmony_ci  const parser = this.parser;
5201cb0ef41Sopenharmony_ci
5211cb0ef41Sopenharmony_ci  if (!req.res && !req.socket._hadError) {
5221cb0ef41Sopenharmony_ci    // If we don't have a response then we know that the socket
5231cb0ef41Sopenharmony_ci    // ended prematurely and we need to emit an error on the request.
5241cb0ef41Sopenharmony_ci    req.socket._hadError = true;
5251cb0ef41Sopenharmony_ci    req.emit('error', connResetException('socket hang up'));
5261cb0ef41Sopenharmony_ci  }
5271cb0ef41Sopenharmony_ci  if (parser) {
5281cb0ef41Sopenharmony_ci    parser.finish();
5291cb0ef41Sopenharmony_ci    freeParser(parser, req, socket);
5301cb0ef41Sopenharmony_ci  }
5311cb0ef41Sopenharmony_ci  socket.destroy();
5321cb0ef41Sopenharmony_ci}
5331cb0ef41Sopenharmony_ci
5341cb0ef41Sopenharmony_cifunction socketOnData(d) {
5351cb0ef41Sopenharmony_ci  const socket = this;
5361cb0ef41Sopenharmony_ci  const req = this._httpMessage;
5371cb0ef41Sopenharmony_ci  const parser = this.parser;
5381cb0ef41Sopenharmony_ci
5391cb0ef41Sopenharmony_ci  assert(parser && parser.socket === socket);
5401cb0ef41Sopenharmony_ci
5411cb0ef41Sopenharmony_ci  const ret = parser.execute(d);
5421cb0ef41Sopenharmony_ci  if (ret instanceof Error) {
5431cb0ef41Sopenharmony_ci    prepareError(ret, parser, d);
5441cb0ef41Sopenharmony_ci    debug('parse error', ret);
5451cb0ef41Sopenharmony_ci    freeParser(parser, req, socket);
5461cb0ef41Sopenharmony_ci    socket.removeListener('data', socketOnData);
5471cb0ef41Sopenharmony_ci    socket.removeListener('end', socketOnEnd);
5481cb0ef41Sopenharmony_ci    socket.destroy();
5491cb0ef41Sopenharmony_ci    req.socket._hadError = true;
5501cb0ef41Sopenharmony_ci    req.emit('error', ret);
5511cb0ef41Sopenharmony_ci  } else if (parser.incoming && parser.incoming.upgrade) {
5521cb0ef41Sopenharmony_ci    // Upgrade (if status code 101) or CONNECT
5531cb0ef41Sopenharmony_ci    const bytesParsed = ret;
5541cb0ef41Sopenharmony_ci    const res = parser.incoming;
5551cb0ef41Sopenharmony_ci    req.res = res;
5561cb0ef41Sopenharmony_ci
5571cb0ef41Sopenharmony_ci    socket.removeListener('data', socketOnData);
5581cb0ef41Sopenharmony_ci    socket.removeListener('end', socketOnEnd);
5591cb0ef41Sopenharmony_ci    socket.removeListener('drain', ondrain);
5601cb0ef41Sopenharmony_ci
5611cb0ef41Sopenharmony_ci    if (req.timeoutCb) socket.removeListener('timeout', req.timeoutCb);
5621cb0ef41Sopenharmony_ci    socket.removeListener('timeout', responseOnTimeout);
5631cb0ef41Sopenharmony_ci
5641cb0ef41Sopenharmony_ci    parser.finish();
5651cb0ef41Sopenharmony_ci    freeParser(parser, req, socket);
5661cb0ef41Sopenharmony_ci
5671cb0ef41Sopenharmony_ci    const bodyHead = TypedArrayPrototypeSlice(d, bytesParsed, d.length);
5681cb0ef41Sopenharmony_ci
5691cb0ef41Sopenharmony_ci    const eventName = req.method === 'CONNECT' ? 'connect' : 'upgrade';
5701cb0ef41Sopenharmony_ci    if (req.listenerCount(eventName) > 0) {
5711cb0ef41Sopenharmony_ci      req.upgradeOrConnect = true;
5721cb0ef41Sopenharmony_ci
5731cb0ef41Sopenharmony_ci      // detach the socket
5741cb0ef41Sopenharmony_ci      socket.emit('agentRemove');
5751cb0ef41Sopenharmony_ci      socket.removeListener('close', socketCloseListener);
5761cb0ef41Sopenharmony_ci      socket.removeListener('error', socketErrorListener);
5771cb0ef41Sopenharmony_ci
5781cb0ef41Sopenharmony_ci      socket._httpMessage = null;
5791cb0ef41Sopenharmony_ci      socket.readableFlowing = null;
5801cb0ef41Sopenharmony_ci
5811cb0ef41Sopenharmony_ci      req.emit(eventName, res, socket, bodyHead);
5821cb0ef41Sopenharmony_ci      req.destroyed = true;
5831cb0ef41Sopenharmony_ci      req._closed = true;
5841cb0ef41Sopenharmony_ci      req.emit('close');
5851cb0ef41Sopenharmony_ci    } else {
5861cb0ef41Sopenharmony_ci      // Requested Upgrade or used CONNECT method, but have no handler.
5871cb0ef41Sopenharmony_ci      socket.destroy();
5881cb0ef41Sopenharmony_ci    }
5891cb0ef41Sopenharmony_ci  } else if (parser.incoming && parser.incoming.complete &&
5901cb0ef41Sopenharmony_ci             // When the status code is informational (100, 102-199),
5911cb0ef41Sopenharmony_ci             // the server will send a final response after this client
5921cb0ef41Sopenharmony_ci             // sends a request body, so we must not free the parser.
5931cb0ef41Sopenharmony_ci             // 101 (Switching Protocols) and all other status codes
5941cb0ef41Sopenharmony_ci             // should be processed normally.
5951cb0ef41Sopenharmony_ci             !statusIsInformational(parser.incoming.statusCode)) {
5961cb0ef41Sopenharmony_ci    socket.removeListener('data', socketOnData);
5971cb0ef41Sopenharmony_ci    socket.removeListener('end', socketOnEnd);
5981cb0ef41Sopenharmony_ci    socket.removeListener('drain', ondrain);
5991cb0ef41Sopenharmony_ci    freeParser(parser, req, socket);
6001cb0ef41Sopenharmony_ci  }
6011cb0ef41Sopenharmony_ci}
6021cb0ef41Sopenharmony_ci
6031cb0ef41Sopenharmony_cifunction statusIsInformational(status) {
6041cb0ef41Sopenharmony_ci  // 100 (Continue)    RFC7231 Section 6.2.1
6051cb0ef41Sopenharmony_ci  // 102 (Processing)  RFC2518
6061cb0ef41Sopenharmony_ci  // 103 (Early Hints) RFC8297
6071cb0ef41Sopenharmony_ci  // 104-199 (Unassigned)
6081cb0ef41Sopenharmony_ci  return (status < 200 && status >= 100 && status !== 101);
6091cb0ef41Sopenharmony_ci}
6101cb0ef41Sopenharmony_ci
6111cb0ef41Sopenharmony_ci// client
6121cb0ef41Sopenharmony_cifunction parserOnIncomingClient(res, shouldKeepAlive) {
6131cb0ef41Sopenharmony_ci  const socket = this.socket;
6141cb0ef41Sopenharmony_ci  const req = socket._httpMessage;
6151cb0ef41Sopenharmony_ci
6161cb0ef41Sopenharmony_ci  debug('AGENT incoming response!');
6171cb0ef41Sopenharmony_ci
6181cb0ef41Sopenharmony_ci  if (req.res) {
6191cb0ef41Sopenharmony_ci    // We already have a response object, this means the server
6201cb0ef41Sopenharmony_ci    // sent a double response.
6211cb0ef41Sopenharmony_ci    socket.destroy();
6221cb0ef41Sopenharmony_ci    return 0;  // No special treatment.
6231cb0ef41Sopenharmony_ci  }
6241cb0ef41Sopenharmony_ci  req.res = res;
6251cb0ef41Sopenharmony_ci
6261cb0ef41Sopenharmony_ci  // Skip body and treat as Upgrade.
6271cb0ef41Sopenharmony_ci  if (res.upgrade)
6281cb0ef41Sopenharmony_ci    return 2;
6291cb0ef41Sopenharmony_ci
6301cb0ef41Sopenharmony_ci  // Responses to CONNECT request is handled as Upgrade.
6311cb0ef41Sopenharmony_ci  const method = req.method;
6321cb0ef41Sopenharmony_ci  if (method === 'CONNECT') {
6331cb0ef41Sopenharmony_ci    res.upgrade = true;
6341cb0ef41Sopenharmony_ci    return 2;  // Skip body and treat as Upgrade.
6351cb0ef41Sopenharmony_ci  }
6361cb0ef41Sopenharmony_ci
6371cb0ef41Sopenharmony_ci  if (statusIsInformational(res.statusCode)) {
6381cb0ef41Sopenharmony_ci    // Restart the parser, as this is a 1xx informational message.
6391cb0ef41Sopenharmony_ci    req.res = null; // Clear res so that we don't hit double-responses.
6401cb0ef41Sopenharmony_ci    // Maintain compatibility by sending 100-specific events
6411cb0ef41Sopenharmony_ci    if (res.statusCode === 100) {
6421cb0ef41Sopenharmony_ci      req.emit('continue');
6431cb0ef41Sopenharmony_ci    }
6441cb0ef41Sopenharmony_ci    // Send information events to all 1xx responses except 101 Upgrade.
6451cb0ef41Sopenharmony_ci    req.emit('information', {
6461cb0ef41Sopenharmony_ci      statusCode: res.statusCode,
6471cb0ef41Sopenharmony_ci      statusMessage: res.statusMessage,
6481cb0ef41Sopenharmony_ci      httpVersion: res.httpVersion,
6491cb0ef41Sopenharmony_ci      httpVersionMajor: res.httpVersionMajor,
6501cb0ef41Sopenharmony_ci      httpVersionMinor: res.httpVersionMinor,
6511cb0ef41Sopenharmony_ci      headers: res.headers,
6521cb0ef41Sopenharmony_ci      rawHeaders: res.rawHeaders,
6531cb0ef41Sopenharmony_ci    });
6541cb0ef41Sopenharmony_ci
6551cb0ef41Sopenharmony_ci    return 1;  // Skip body but don't treat as Upgrade.
6561cb0ef41Sopenharmony_ci  }
6571cb0ef41Sopenharmony_ci
6581cb0ef41Sopenharmony_ci  if (req.shouldKeepAlive && !shouldKeepAlive && !req.upgradeOrConnect) {
6591cb0ef41Sopenharmony_ci    // Server MUST respond with Connection:keep-alive for us to enable it.
6601cb0ef41Sopenharmony_ci    // If we've been upgraded (via WebSockets) we also shouldn't try to
6611cb0ef41Sopenharmony_ci    // keep the connection open.
6621cb0ef41Sopenharmony_ci    req.shouldKeepAlive = false;
6631cb0ef41Sopenharmony_ci  }
6641cb0ef41Sopenharmony_ci
6651cb0ef41Sopenharmony_ci  DTRACE_HTTP_CLIENT_RESPONSE(socket, req);
6661cb0ef41Sopenharmony_ci  if (req[kClientRequestStatistics] && hasObserver('http')) {
6671cb0ef41Sopenharmony_ci    stopPerf(req, kClientRequestStatistics, {
6681cb0ef41Sopenharmony_ci      detail: {
6691cb0ef41Sopenharmony_ci        res: {
6701cb0ef41Sopenharmony_ci          statusCode: res.statusCode,
6711cb0ef41Sopenharmony_ci          statusMessage: res.statusMessage,
6721cb0ef41Sopenharmony_ci          headers: res.headers,
6731cb0ef41Sopenharmony_ci        },
6741cb0ef41Sopenharmony_ci      },
6751cb0ef41Sopenharmony_ci    });
6761cb0ef41Sopenharmony_ci  }
6771cb0ef41Sopenharmony_ci  if (onClientResponseFinishChannel.hasSubscribers) {
6781cb0ef41Sopenharmony_ci    onClientResponseFinishChannel.publish({
6791cb0ef41Sopenharmony_ci      request: req,
6801cb0ef41Sopenharmony_ci      response: res,
6811cb0ef41Sopenharmony_ci    });
6821cb0ef41Sopenharmony_ci  }
6831cb0ef41Sopenharmony_ci  if (isTraceHTTPEnabled() && typeof req._traceEventId === 'number') {
6841cb0ef41Sopenharmony_ci    traceEnd(HTTP_CLIENT_TRACE_EVENT_NAME, req._traceEventId, {
6851cb0ef41Sopenharmony_ci      path: req.path,
6861cb0ef41Sopenharmony_ci      statusCode: res.statusCode,
6871cb0ef41Sopenharmony_ci    });
6881cb0ef41Sopenharmony_ci  }
6891cb0ef41Sopenharmony_ci  req.res = res;
6901cb0ef41Sopenharmony_ci  res.req = req;
6911cb0ef41Sopenharmony_ci
6921cb0ef41Sopenharmony_ci  // Add our listener first, so that we guarantee socket cleanup
6931cb0ef41Sopenharmony_ci  res.on('end', responseOnEnd);
6941cb0ef41Sopenharmony_ci  req.on('finish', requestOnFinish);
6951cb0ef41Sopenharmony_ci  socket.on('timeout', responseOnTimeout);
6961cb0ef41Sopenharmony_ci
6971cb0ef41Sopenharmony_ci  // If the user did not listen for the 'response' event, then they
6981cb0ef41Sopenharmony_ci  // can't possibly read the data, so we ._dump() it into the void
6991cb0ef41Sopenharmony_ci  // so that the socket doesn't hang there in a paused state.
7001cb0ef41Sopenharmony_ci  if (req.aborted || !req.emit('response', res))
7011cb0ef41Sopenharmony_ci    res._dump();
7021cb0ef41Sopenharmony_ci
7031cb0ef41Sopenharmony_ci  if (method === 'HEAD')
7041cb0ef41Sopenharmony_ci    return 1;  // Skip body but don't treat as Upgrade.
7051cb0ef41Sopenharmony_ci
7061cb0ef41Sopenharmony_ci  if (res.statusCode === 304) {
7071cb0ef41Sopenharmony_ci    res.complete = true;
7081cb0ef41Sopenharmony_ci    return 1; // Skip body as there won't be any
7091cb0ef41Sopenharmony_ci  }
7101cb0ef41Sopenharmony_ci
7111cb0ef41Sopenharmony_ci  return 0;  // No special treatment.
7121cb0ef41Sopenharmony_ci}
7131cb0ef41Sopenharmony_ci
7141cb0ef41Sopenharmony_ci// client
7151cb0ef41Sopenharmony_cifunction responseKeepAlive(req) {
7161cb0ef41Sopenharmony_ci  const socket = req.socket;
7171cb0ef41Sopenharmony_ci
7181cb0ef41Sopenharmony_ci  debug('AGENT socket keep-alive');
7191cb0ef41Sopenharmony_ci  if (req.timeoutCb) {
7201cb0ef41Sopenharmony_ci    socket.setTimeout(0, req.timeoutCb);
7211cb0ef41Sopenharmony_ci    req.timeoutCb = null;
7221cb0ef41Sopenharmony_ci  }
7231cb0ef41Sopenharmony_ci  socket.removeListener('close', socketCloseListener);
7241cb0ef41Sopenharmony_ci  socket.removeListener('error', socketErrorListener);
7251cb0ef41Sopenharmony_ci  socket.removeListener('data', socketOnData);
7261cb0ef41Sopenharmony_ci  socket.removeListener('end', socketOnEnd);
7271cb0ef41Sopenharmony_ci
7281cb0ef41Sopenharmony_ci  // TODO(ronag): Between here and emitFreeNT the socket
7291cb0ef41Sopenharmony_ci  // has no 'error' handler.
7301cb0ef41Sopenharmony_ci
7311cb0ef41Sopenharmony_ci  // There are cases where _handle === null. Avoid those. Passing undefined to
7321cb0ef41Sopenharmony_ci  // nextTick() will call getDefaultTriggerAsyncId() to retrieve the id.
7331cb0ef41Sopenharmony_ci  const asyncId = socket._handle ? socket._handle.getAsyncId() : undefined;
7341cb0ef41Sopenharmony_ci  // Mark this socket as available, AFTER user-added end
7351cb0ef41Sopenharmony_ci  // handlers have a chance to run.
7361cb0ef41Sopenharmony_ci  defaultTriggerAsyncIdScope(asyncId, process.nextTick, emitFreeNT, req);
7371cb0ef41Sopenharmony_ci
7381cb0ef41Sopenharmony_ci  req.destroyed = true;
7391cb0ef41Sopenharmony_ci  if (req.res) {
7401cb0ef41Sopenharmony_ci    // Detach socket from IncomingMessage to avoid destroying the freed
7411cb0ef41Sopenharmony_ci    // socket in IncomingMessage.destroy().
7421cb0ef41Sopenharmony_ci    req.res.socket = null;
7431cb0ef41Sopenharmony_ci  }
7441cb0ef41Sopenharmony_ci}
7451cb0ef41Sopenharmony_ci
7461cb0ef41Sopenharmony_cifunction responseOnEnd() {
7471cb0ef41Sopenharmony_ci  const req = this.req;
7481cb0ef41Sopenharmony_ci  const socket = req.socket;
7491cb0ef41Sopenharmony_ci
7501cb0ef41Sopenharmony_ci  if (socket) {
7511cb0ef41Sopenharmony_ci    if (req.timeoutCb) socket.removeListener('timeout', emitRequestTimeout);
7521cb0ef41Sopenharmony_ci    socket.removeListener('timeout', responseOnTimeout);
7531cb0ef41Sopenharmony_ci  }
7541cb0ef41Sopenharmony_ci
7551cb0ef41Sopenharmony_ci  req._ended = true;
7561cb0ef41Sopenharmony_ci
7571cb0ef41Sopenharmony_ci  if (!req.shouldKeepAlive) {
7581cb0ef41Sopenharmony_ci    if (socket.writable) {
7591cb0ef41Sopenharmony_ci      debug('AGENT socket.destroySoon()');
7601cb0ef41Sopenharmony_ci      if (typeof socket.destroySoon === 'function')
7611cb0ef41Sopenharmony_ci        socket.destroySoon();
7621cb0ef41Sopenharmony_ci      else
7631cb0ef41Sopenharmony_ci        socket.end();
7641cb0ef41Sopenharmony_ci    }
7651cb0ef41Sopenharmony_ci    assert(!socket.writable);
7661cb0ef41Sopenharmony_ci  } else if (req.writableFinished && !this.aborted) {
7671cb0ef41Sopenharmony_ci    assert(req.finished);
7681cb0ef41Sopenharmony_ci    // We can assume `req.finished` means all data has been written since:
7691cb0ef41Sopenharmony_ci    // - `'responseOnEnd'` means we have been assigned a socket.
7701cb0ef41Sopenharmony_ci    // - when we have a socket we write directly to it without buffering.
7711cb0ef41Sopenharmony_ci    // - `req.finished` means `end()` has been called and no further data.
7721cb0ef41Sopenharmony_ci    //   can be written
7731cb0ef41Sopenharmony_ci    // In addition, `req.writableFinished` means all data written has been
7741cb0ef41Sopenharmony_ci    // accepted by the kernel. (i.e. the `req.socket` is drained).Without
7751cb0ef41Sopenharmony_ci    // this constraint, we may assign a non drained socket to a request.
7761cb0ef41Sopenharmony_ci    responseKeepAlive(req);
7771cb0ef41Sopenharmony_ci  }
7781cb0ef41Sopenharmony_ci}
7791cb0ef41Sopenharmony_ci
7801cb0ef41Sopenharmony_cifunction responseOnTimeout() {
7811cb0ef41Sopenharmony_ci  const req = this._httpMessage;
7821cb0ef41Sopenharmony_ci  if (!req) return;
7831cb0ef41Sopenharmony_ci  const res = req.res;
7841cb0ef41Sopenharmony_ci  if (!res) return;
7851cb0ef41Sopenharmony_ci  res.emit('timeout');
7861cb0ef41Sopenharmony_ci}
7871cb0ef41Sopenharmony_ci
7881cb0ef41Sopenharmony_ci// This function is necessary in the case where we receive the entire response
7891cb0ef41Sopenharmony_ci// from the server before we finish sending out the request.
7901cb0ef41Sopenharmony_cifunction requestOnFinish() {
7911cb0ef41Sopenharmony_ci  const req = this;
7921cb0ef41Sopenharmony_ci
7931cb0ef41Sopenharmony_ci  if (req.shouldKeepAlive && req._ended)
7941cb0ef41Sopenharmony_ci    responseKeepAlive(req);
7951cb0ef41Sopenharmony_ci}
7961cb0ef41Sopenharmony_ci
7971cb0ef41Sopenharmony_cifunction emitFreeNT(req) {
7981cb0ef41Sopenharmony_ci  req._closed = true;
7991cb0ef41Sopenharmony_ci  req.emit('close');
8001cb0ef41Sopenharmony_ci  if (req.socket) {
8011cb0ef41Sopenharmony_ci    req.socket.emit('free');
8021cb0ef41Sopenharmony_ci  }
8031cb0ef41Sopenharmony_ci}
8041cb0ef41Sopenharmony_ci
8051cb0ef41Sopenharmony_cifunction tickOnSocket(req, socket) {
8061cb0ef41Sopenharmony_ci  const parser = parsers.alloc();
8071cb0ef41Sopenharmony_ci  req.socket = socket;
8081cb0ef41Sopenharmony_ci  const lenient = req.insecureHTTPParser === undefined ?
8091cb0ef41Sopenharmony_ci    isLenient() : req.insecureHTTPParser;
8101cb0ef41Sopenharmony_ci  parser.initialize(HTTPParser.RESPONSE,
8111cb0ef41Sopenharmony_ci                    new HTTPClientAsyncResource('HTTPINCOMINGMESSAGE', req),
8121cb0ef41Sopenharmony_ci                    req.maxHeaderSize || 0,
8131cb0ef41Sopenharmony_ci                    lenient ? kLenientAll : kLenientNone);
8141cb0ef41Sopenharmony_ci  parser.socket = socket;
8151cb0ef41Sopenharmony_ci  parser.outgoing = req;
8161cb0ef41Sopenharmony_ci  req.parser = parser;
8171cb0ef41Sopenharmony_ci
8181cb0ef41Sopenharmony_ci  socket.parser = parser;
8191cb0ef41Sopenharmony_ci  socket._httpMessage = req;
8201cb0ef41Sopenharmony_ci
8211cb0ef41Sopenharmony_ci  // Propagate headers limit from request object to parser
8221cb0ef41Sopenharmony_ci  if (typeof req.maxHeadersCount === 'number') {
8231cb0ef41Sopenharmony_ci    parser.maxHeaderPairs = req.maxHeadersCount << 1;
8241cb0ef41Sopenharmony_ci  }
8251cb0ef41Sopenharmony_ci
8261cb0ef41Sopenharmony_ci  parser.joinDuplicateHeaders = req.joinDuplicateHeaders;
8271cb0ef41Sopenharmony_ci
8281cb0ef41Sopenharmony_ci  parser.onIncoming = parserOnIncomingClient;
8291cb0ef41Sopenharmony_ci  socket.on('error', socketErrorListener);
8301cb0ef41Sopenharmony_ci  socket.on('data', socketOnData);
8311cb0ef41Sopenharmony_ci  socket.on('end', socketOnEnd);
8321cb0ef41Sopenharmony_ci  socket.on('close', socketCloseListener);
8331cb0ef41Sopenharmony_ci  socket.on('drain', ondrain);
8341cb0ef41Sopenharmony_ci
8351cb0ef41Sopenharmony_ci  if (
8361cb0ef41Sopenharmony_ci    req.timeout !== undefined ||
8371cb0ef41Sopenharmony_ci    (req.agent && req.agent.options && req.agent.options.timeout)
8381cb0ef41Sopenharmony_ci  ) {
8391cb0ef41Sopenharmony_ci    listenSocketTimeout(req);
8401cb0ef41Sopenharmony_ci  }
8411cb0ef41Sopenharmony_ci  req.emit('socket', socket);
8421cb0ef41Sopenharmony_ci}
8431cb0ef41Sopenharmony_ci
8441cb0ef41Sopenharmony_cifunction emitRequestTimeout() {
8451cb0ef41Sopenharmony_ci  const req = this._httpMessage;
8461cb0ef41Sopenharmony_ci  if (req) {
8471cb0ef41Sopenharmony_ci    req.emit('timeout');
8481cb0ef41Sopenharmony_ci  }
8491cb0ef41Sopenharmony_ci}
8501cb0ef41Sopenharmony_ci
8511cb0ef41Sopenharmony_cifunction listenSocketTimeout(req) {
8521cb0ef41Sopenharmony_ci  if (req.timeoutCb) {
8531cb0ef41Sopenharmony_ci    return;
8541cb0ef41Sopenharmony_ci  }
8551cb0ef41Sopenharmony_ci  // Set timeoutCb so it will get cleaned up on request end.
8561cb0ef41Sopenharmony_ci  req.timeoutCb = emitRequestTimeout;
8571cb0ef41Sopenharmony_ci  // Delegate socket timeout event.
8581cb0ef41Sopenharmony_ci  if (req.socket) {
8591cb0ef41Sopenharmony_ci    req.socket.once('timeout', emitRequestTimeout);
8601cb0ef41Sopenharmony_ci  } else {
8611cb0ef41Sopenharmony_ci    req.on('socket', (socket) => {
8621cb0ef41Sopenharmony_ci      socket.once('timeout', emitRequestTimeout);
8631cb0ef41Sopenharmony_ci    });
8641cb0ef41Sopenharmony_ci  }
8651cb0ef41Sopenharmony_ci}
8661cb0ef41Sopenharmony_ci
8671cb0ef41Sopenharmony_ciClientRequest.prototype.onSocket = function onSocket(socket, err) {
8681cb0ef41Sopenharmony_ci  // TODO(ronag): Between here and onSocketNT the socket
8691cb0ef41Sopenharmony_ci  // has no 'error' handler.
8701cb0ef41Sopenharmony_ci  process.nextTick(onSocketNT, this, socket, err);
8711cb0ef41Sopenharmony_ci};
8721cb0ef41Sopenharmony_ci
8731cb0ef41Sopenharmony_cifunction onSocketNT(req, socket, err) {
8741cb0ef41Sopenharmony_ci  if (req.destroyed || err) {
8751cb0ef41Sopenharmony_ci    req.destroyed = true;
8761cb0ef41Sopenharmony_ci
8771cb0ef41Sopenharmony_ci    function _destroy(req, err) {
8781cb0ef41Sopenharmony_ci      if (!req.aborted && !err) {
8791cb0ef41Sopenharmony_ci        err = connResetException('socket hang up');
8801cb0ef41Sopenharmony_ci      }
8811cb0ef41Sopenharmony_ci      if (err) {
8821cb0ef41Sopenharmony_ci        req.emit('error', err);
8831cb0ef41Sopenharmony_ci      }
8841cb0ef41Sopenharmony_ci      req._closed = true;
8851cb0ef41Sopenharmony_ci      req.emit('close');
8861cb0ef41Sopenharmony_ci    }
8871cb0ef41Sopenharmony_ci
8881cb0ef41Sopenharmony_ci    if (socket) {
8891cb0ef41Sopenharmony_ci      if (!err && req.agent && !socket.destroyed) {
8901cb0ef41Sopenharmony_ci        socket.emit('free');
8911cb0ef41Sopenharmony_ci      } else {
8921cb0ef41Sopenharmony_ci        finished(socket.destroy(err || req[kError]), (er) => {
8931cb0ef41Sopenharmony_ci          if (er?.code === 'ERR_STREAM_PREMATURE_CLOSE') {
8941cb0ef41Sopenharmony_ci            er = null;
8951cb0ef41Sopenharmony_ci          }
8961cb0ef41Sopenharmony_ci          _destroy(req, er || err);
8971cb0ef41Sopenharmony_ci        });
8981cb0ef41Sopenharmony_ci        return;
8991cb0ef41Sopenharmony_ci      }
9001cb0ef41Sopenharmony_ci    }
9011cb0ef41Sopenharmony_ci
9021cb0ef41Sopenharmony_ci    _destroy(req, err || req[kError]);
9031cb0ef41Sopenharmony_ci  } else {
9041cb0ef41Sopenharmony_ci    tickOnSocket(req, socket);
9051cb0ef41Sopenharmony_ci    req._flush();
9061cb0ef41Sopenharmony_ci  }
9071cb0ef41Sopenharmony_ci}
9081cb0ef41Sopenharmony_ci
9091cb0ef41Sopenharmony_ciClientRequest.prototype._deferToConnect = _deferToConnect;
9101cb0ef41Sopenharmony_cifunction _deferToConnect(method, arguments_) {
9111cb0ef41Sopenharmony_ci  // This function is for calls that need to happen once the socket is
9121cb0ef41Sopenharmony_ci  // assigned to this request and writable. It's an important promisy
9131cb0ef41Sopenharmony_ci  // thing for all the socket calls that happen either now
9141cb0ef41Sopenharmony_ci  // (when a socket is assigned) or in the future (when a socket gets
9151cb0ef41Sopenharmony_ci  // assigned out of the pool and is eventually writable).
9161cb0ef41Sopenharmony_ci
9171cb0ef41Sopenharmony_ci  const callSocketMethod = () => {
9181cb0ef41Sopenharmony_ci    if (method)
9191cb0ef41Sopenharmony_ci      ReflectApply(this.socket[method], this.socket, arguments_);
9201cb0ef41Sopenharmony_ci  };
9211cb0ef41Sopenharmony_ci
9221cb0ef41Sopenharmony_ci  const onSocket = () => {
9231cb0ef41Sopenharmony_ci    if (this.socket.writable) {
9241cb0ef41Sopenharmony_ci      callSocketMethod();
9251cb0ef41Sopenharmony_ci    } else {
9261cb0ef41Sopenharmony_ci      this.socket.once('connect', callSocketMethod);
9271cb0ef41Sopenharmony_ci    }
9281cb0ef41Sopenharmony_ci  };
9291cb0ef41Sopenharmony_ci
9301cb0ef41Sopenharmony_ci  if (!this.socket) {
9311cb0ef41Sopenharmony_ci    this.once('socket', onSocket);
9321cb0ef41Sopenharmony_ci  } else {
9331cb0ef41Sopenharmony_ci    onSocket();
9341cb0ef41Sopenharmony_ci  }
9351cb0ef41Sopenharmony_ci}
9361cb0ef41Sopenharmony_ci
9371cb0ef41Sopenharmony_ciClientRequest.prototype.setTimeout = function setTimeout(msecs, callback) {
9381cb0ef41Sopenharmony_ci  if (this._ended) {
9391cb0ef41Sopenharmony_ci    return this;
9401cb0ef41Sopenharmony_ci  }
9411cb0ef41Sopenharmony_ci
9421cb0ef41Sopenharmony_ci  listenSocketTimeout(this);
9431cb0ef41Sopenharmony_ci  msecs = getTimerDuration(msecs, 'msecs');
9441cb0ef41Sopenharmony_ci  if (callback) this.once('timeout', callback);
9451cb0ef41Sopenharmony_ci
9461cb0ef41Sopenharmony_ci  if (this.socket) {
9471cb0ef41Sopenharmony_ci    setSocketTimeout(this.socket, msecs);
9481cb0ef41Sopenharmony_ci  } else {
9491cb0ef41Sopenharmony_ci    this.once('socket', (sock) => setSocketTimeout(sock, msecs));
9501cb0ef41Sopenharmony_ci  }
9511cb0ef41Sopenharmony_ci
9521cb0ef41Sopenharmony_ci  return this;
9531cb0ef41Sopenharmony_ci};
9541cb0ef41Sopenharmony_ci
9551cb0ef41Sopenharmony_cifunction setSocketTimeout(sock, msecs) {
9561cb0ef41Sopenharmony_ci  if (sock.connecting) {
9571cb0ef41Sopenharmony_ci    sock.once('connect', function() {
9581cb0ef41Sopenharmony_ci      sock.setTimeout(msecs);
9591cb0ef41Sopenharmony_ci    });
9601cb0ef41Sopenharmony_ci  } else {
9611cb0ef41Sopenharmony_ci    sock.setTimeout(msecs);
9621cb0ef41Sopenharmony_ci  }
9631cb0ef41Sopenharmony_ci}
9641cb0ef41Sopenharmony_ci
9651cb0ef41Sopenharmony_ciClientRequest.prototype.setNoDelay = function setNoDelay(noDelay) {
9661cb0ef41Sopenharmony_ci  this._deferToConnect('setNoDelay', [noDelay]);
9671cb0ef41Sopenharmony_ci};
9681cb0ef41Sopenharmony_ci
9691cb0ef41Sopenharmony_ciClientRequest.prototype.setSocketKeepAlive =
9701cb0ef41Sopenharmony_ci    function setSocketKeepAlive(enable, initialDelay) {
9711cb0ef41Sopenharmony_ci      this._deferToConnect('setKeepAlive', [enable, initialDelay]);
9721cb0ef41Sopenharmony_ci    };
9731cb0ef41Sopenharmony_ci
9741cb0ef41Sopenharmony_ciClientRequest.prototype.clearTimeout = function clearTimeout(cb) {
9751cb0ef41Sopenharmony_ci  this.setTimeout(0, cb);
9761cb0ef41Sopenharmony_ci};
9771cb0ef41Sopenharmony_ci
9781cb0ef41Sopenharmony_cimodule.exports = {
9791cb0ef41Sopenharmony_ci  ClientRequest,
9801cb0ef41Sopenharmony_ci};
981