11cb0ef41Sopenharmony_ci// @ts-check
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ci'use strict'
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci/* global WebAssembly */
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ciconst assert = require('assert')
81cb0ef41Sopenharmony_ciconst net = require('net')
91cb0ef41Sopenharmony_ciconst http = require('http')
101cb0ef41Sopenharmony_ciconst { pipeline } = require('stream')
111cb0ef41Sopenharmony_ciconst util = require('./core/util')
121cb0ef41Sopenharmony_ciconst timers = require('./timers')
131cb0ef41Sopenharmony_ciconst Request = require('./core/request')
141cb0ef41Sopenharmony_ciconst DispatcherBase = require('./dispatcher-base')
151cb0ef41Sopenharmony_ciconst {
161cb0ef41Sopenharmony_ci  RequestContentLengthMismatchError,
171cb0ef41Sopenharmony_ci  ResponseContentLengthMismatchError,
181cb0ef41Sopenharmony_ci  InvalidArgumentError,
191cb0ef41Sopenharmony_ci  RequestAbortedError,
201cb0ef41Sopenharmony_ci  HeadersTimeoutError,
211cb0ef41Sopenharmony_ci  HeadersOverflowError,
221cb0ef41Sopenharmony_ci  SocketError,
231cb0ef41Sopenharmony_ci  InformationalError,
241cb0ef41Sopenharmony_ci  BodyTimeoutError,
251cb0ef41Sopenharmony_ci  HTTPParserError,
261cb0ef41Sopenharmony_ci  ResponseExceededMaxSizeError,
271cb0ef41Sopenharmony_ci  ClientDestroyedError
281cb0ef41Sopenharmony_ci} = require('./core/errors')
291cb0ef41Sopenharmony_ciconst buildConnector = require('./core/connect')
301cb0ef41Sopenharmony_ciconst {
311cb0ef41Sopenharmony_ci  kUrl,
321cb0ef41Sopenharmony_ci  kReset,
331cb0ef41Sopenharmony_ci  kServerName,
341cb0ef41Sopenharmony_ci  kClient,
351cb0ef41Sopenharmony_ci  kBusy,
361cb0ef41Sopenharmony_ci  kParser,
371cb0ef41Sopenharmony_ci  kConnect,
381cb0ef41Sopenharmony_ci  kBlocking,
391cb0ef41Sopenharmony_ci  kResuming,
401cb0ef41Sopenharmony_ci  kRunning,
411cb0ef41Sopenharmony_ci  kPending,
421cb0ef41Sopenharmony_ci  kSize,
431cb0ef41Sopenharmony_ci  kWriting,
441cb0ef41Sopenharmony_ci  kQueue,
451cb0ef41Sopenharmony_ci  kConnected,
461cb0ef41Sopenharmony_ci  kConnecting,
471cb0ef41Sopenharmony_ci  kNeedDrain,
481cb0ef41Sopenharmony_ci  kNoRef,
491cb0ef41Sopenharmony_ci  kKeepAliveDefaultTimeout,
501cb0ef41Sopenharmony_ci  kHostHeader,
511cb0ef41Sopenharmony_ci  kPendingIdx,
521cb0ef41Sopenharmony_ci  kRunningIdx,
531cb0ef41Sopenharmony_ci  kError,
541cb0ef41Sopenharmony_ci  kPipelining,
551cb0ef41Sopenharmony_ci  kSocket,
561cb0ef41Sopenharmony_ci  kKeepAliveTimeoutValue,
571cb0ef41Sopenharmony_ci  kMaxHeadersSize,
581cb0ef41Sopenharmony_ci  kKeepAliveMaxTimeout,
591cb0ef41Sopenharmony_ci  kKeepAliveTimeoutThreshold,
601cb0ef41Sopenharmony_ci  kHeadersTimeout,
611cb0ef41Sopenharmony_ci  kBodyTimeout,
621cb0ef41Sopenharmony_ci  kStrictContentLength,
631cb0ef41Sopenharmony_ci  kConnector,
641cb0ef41Sopenharmony_ci  kMaxRedirections,
651cb0ef41Sopenharmony_ci  kMaxRequests,
661cb0ef41Sopenharmony_ci  kCounter,
671cb0ef41Sopenharmony_ci  kClose,
681cb0ef41Sopenharmony_ci  kDestroy,
691cb0ef41Sopenharmony_ci  kDispatch,
701cb0ef41Sopenharmony_ci  kInterceptors,
711cb0ef41Sopenharmony_ci  kLocalAddress,
721cb0ef41Sopenharmony_ci  kMaxResponseSize,
731cb0ef41Sopenharmony_ci  kHTTPConnVersion,
741cb0ef41Sopenharmony_ci  // HTTP2
751cb0ef41Sopenharmony_ci  kHost,
761cb0ef41Sopenharmony_ci  kHTTP2Session,
771cb0ef41Sopenharmony_ci  kHTTP2SessionState,
781cb0ef41Sopenharmony_ci  kHTTP2BuildRequest,
791cb0ef41Sopenharmony_ci  kHTTP2CopyHeaders,
801cb0ef41Sopenharmony_ci  kHTTP1BuildRequest
811cb0ef41Sopenharmony_ci} = require('./core/symbols')
821cb0ef41Sopenharmony_ci
831cb0ef41Sopenharmony_ci/** @type {import('http2')} */
841cb0ef41Sopenharmony_cilet http2
851cb0ef41Sopenharmony_citry {
861cb0ef41Sopenharmony_ci  http2 = require('http2')
871cb0ef41Sopenharmony_ci} catch {
881cb0ef41Sopenharmony_ci  // @ts-ignore
891cb0ef41Sopenharmony_ci  http2 = { constants: {} }
901cb0ef41Sopenharmony_ci}
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_ciconst {
931cb0ef41Sopenharmony_ci  constants: {
941cb0ef41Sopenharmony_ci    HTTP2_HEADER_AUTHORITY,
951cb0ef41Sopenharmony_ci    HTTP2_HEADER_METHOD,
961cb0ef41Sopenharmony_ci    HTTP2_HEADER_PATH,
971cb0ef41Sopenharmony_ci    HTTP2_HEADER_SCHEME,
981cb0ef41Sopenharmony_ci    HTTP2_HEADER_CONTENT_LENGTH,
991cb0ef41Sopenharmony_ci    HTTP2_HEADER_EXPECT,
1001cb0ef41Sopenharmony_ci    HTTP2_HEADER_STATUS
1011cb0ef41Sopenharmony_ci  }
1021cb0ef41Sopenharmony_ci} = http2
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ci// Experimental
1051cb0ef41Sopenharmony_cilet h2ExperimentalWarned = false
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_ciconst FastBuffer = Buffer[Symbol.species]
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_ciconst kClosedResolve = Symbol('kClosedResolve')
1101cb0ef41Sopenharmony_ci
1111cb0ef41Sopenharmony_ciconst channels = {}
1121cb0ef41Sopenharmony_ci
1131cb0ef41Sopenharmony_citry {
1141cb0ef41Sopenharmony_ci  const diagnosticsChannel = require('diagnostics_channel')
1151cb0ef41Sopenharmony_ci  channels.sendHeaders = diagnosticsChannel.channel('undici:client:sendHeaders')
1161cb0ef41Sopenharmony_ci  channels.beforeConnect = diagnosticsChannel.channel('undici:client:beforeConnect')
1171cb0ef41Sopenharmony_ci  channels.connectError = diagnosticsChannel.channel('undici:client:connectError')
1181cb0ef41Sopenharmony_ci  channels.connected = diagnosticsChannel.channel('undici:client:connected')
1191cb0ef41Sopenharmony_ci} catch {
1201cb0ef41Sopenharmony_ci  channels.sendHeaders = { hasSubscribers: false }
1211cb0ef41Sopenharmony_ci  channels.beforeConnect = { hasSubscribers: false }
1221cb0ef41Sopenharmony_ci  channels.connectError = { hasSubscribers: false }
1231cb0ef41Sopenharmony_ci  channels.connected = { hasSubscribers: false }
1241cb0ef41Sopenharmony_ci}
1251cb0ef41Sopenharmony_ci
1261cb0ef41Sopenharmony_ci/**
1271cb0ef41Sopenharmony_ci * @type {import('../types/client').default}
1281cb0ef41Sopenharmony_ci */
1291cb0ef41Sopenharmony_ciclass Client extends DispatcherBase {
1301cb0ef41Sopenharmony_ci  /**
1311cb0ef41Sopenharmony_ci   *
1321cb0ef41Sopenharmony_ci   * @param {string|URL} url
1331cb0ef41Sopenharmony_ci   * @param {import('../types/client').Client.Options} options
1341cb0ef41Sopenharmony_ci   */
1351cb0ef41Sopenharmony_ci  constructor (url, {
1361cb0ef41Sopenharmony_ci    interceptors,
1371cb0ef41Sopenharmony_ci    maxHeaderSize,
1381cb0ef41Sopenharmony_ci    headersTimeout,
1391cb0ef41Sopenharmony_ci    socketTimeout,
1401cb0ef41Sopenharmony_ci    requestTimeout,
1411cb0ef41Sopenharmony_ci    connectTimeout,
1421cb0ef41Sopenharmony_ci    bodyTimeout,
1431cb0ef41Sopenharmony_ci    idleTimeout,
1441cb0ef41Sopenharmony_ci    keepAlive,
1451cb0ef41Sopenharmony_ci    keepAliveTimeout,
1461cb0ef41Sopenharmony_ci    maxKeepAliveTimeout,
1471cb0ef41Sopenharmony_ci    keepAliveMaxTimeout,
1481cb0ef41Sopenharmony_ci    keepAliveTimeoutThreshold,
1491cb0ef41Sopenharmony_ci    socketPath,
1501cb0ef41Sopenharmony_ci    pipelining,
1511cb0ef41Sopenharmony_ci    tls,
1521cb0ef41Sopenharmony_ci    strictContentLength,
1531cb0ef41Sopenharmony_ci    maxCachedSessions,
1541cb0ef41Sopenharmony_ci    maxRedirections,
1551cb0ef41Sopenharmony_ci    connect,
1561cb0ef41Sopenharmony_ci    maxRequestsPerClient,
1571cb0ef41Sopenharmony_ci    localAddress,
1581cb0ef41Sopenharmony_ci    maxResponseSize,
1591cb0ef41Sopenharmony_ci    autoSelectFamily,
1601cb0ef41Sopenharmony_ci    autoSelectFamilyAttemptTimeout,
1611cb0ef41Sopenharmony_ci    // h2
1621cb0ef41Sopenharmony_ci    allowH2,
1631cb0ef41Sopenharmony_ci    maxConcurrentStreams
1641cb0ef41Sopenharmony_ci  } = {}) {
1651cb0ef41Sopenharmony_ci    super()
1661cb0ef41Sopenharmony_ci
1671cb0ef41Sopenharmony_ci    if (keepAlive !== undefined) {
1681cb0ef41Sopenharmony_ci      throw new InvalidArgumentError('unsupported keepAlive, use pipelining=0 instead')
1691cb0ef41Sopenharmony_ci    }
1701cb0ef41Sopenharmony_ci
1711cb0ef41Sopenharmony_ci    if (socketTimeout !== undefined) {
1721cb0ef41Sopenharmony_ci      throw new InvalidArgumentError('unsupported socketTimeout, use headersTimeout & bodyTimeout instead')
1731cb0ef41Sopenharmony_ci    }
1741cb0ef41Sopenharmony_ci
1751cb0ef41Sopenharmony_ci    if (requestTimeout !== undefined) {
1761cb0ef41Sopenharmony_ci      throw new InvalidArgumentError('unsupported requestTimeout, use headersTimeout & bodyTimeout instead')
1771cb0ef41Sopenharmony_ci    }
1781cb0ef41Sopenharmony_ci
1791cb0ef41Sopenharmony_ci    if (idleTimeout !== undefined) {
1801cb0ef41Sopenharmony_ci      throw new InvalidArgumentError('unsupported idleTimeout, use keepAliveTimeout instead')
1811cb0ef41Sopenharmony_ci    }
1821cb0ef41Sopenharmony_ci
1831cb0ef41Sopenharmony_ci    if (maxKeepAliveTimeout !== undefined) {
1841cb0ef41Sopenharmony_ci      throw new InvalidArgumentError('unsupported maxKeepAliveTimeout, use keepAliveMaxTimeout instead')
1851cb0ef41Sopenharmony_ci    }
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ci    if (maxHeaderSize != null && !Number.isFinite(maxHeaderSize)) {
1881cb0ef41Sopenharmony_ci      throw new InvalidArgumentError('invalid maxHeaderSize')
1891cb0ef41Sopenharmony_ci    }
1901cb0ef41Sopenharmony_ci
1911cb0ef41Sopenharmony_ci    if (socketPath != null && typeof socketPath !== 'string') {
1921cb0ef41Sopenharmony_ci      throw new InvalidArgumentError('invalid socketPath')
1931cb0ef41Sopenharmony_ci    }
1941cb0ef41Sopenharmony_ci
1951cb0ef41Sopenharmony_ci    if (connectTimeout != null && (!Number.isFinite(connectTimeout) || connectTimeout < 0)) {
1961cb0ef41Sopenharmony_ci      throw new InvalidArgumentError('invalid connectTimeout')
1971cb0ef41Sopenharmony_ci    }
1981cb0ef41Sopenharmony_ci
1991cb0ef41Sopenharmony_ci    if (keepAliveTimeout != null && (!Number.isFinite(keepAliveTimeout) || keepAliveTimeout <= 0)) {
2001cb0ef41Sopenharmony_ci      throw new InvalidArgumentError('invalid keepAliveTimeout')
2011cb0ef41Sopenharmony_ci    }
2021cb0ef41Sopenharmony_ci
2031cb0ef41Sopenharmony_ci    if (keepAliveMaxTimeout != null && (!Number.isFinite(keepAliveMaxTimeout) || keepAliveMaxTimeout <= 0)) {
2041cb0ef41Sopenharmony_ci      throw new InvalidArgumentError('invalid keepAliveMaxTimeout')
2051cb0ef41Sopenharmony_ci    }
2061cb0ef41Sopenharmony_ci
2071cb0ef41Sopenharmony_ci    if (keepAliveTimeoutThreshold != null && !Number.isFinite(keepAliveTimeoutThreshold)) {
2081cb0ef41Sopenharmony_ci      throw new InvalidArgumentError('invalid keepAliveTimeoutThreshold')
2091cb0ef41Sopenharmony_ci    }
2101cb0ef41Sopenharmony_ci
2111cb0ef41Sopenharmony_ci    if (headersTimeout != null && (!Number.isInteger(headersTimeout) || headersTimeout < 0)) {
2121cb0ef41Sopenharmony_ci      throw new InvalidArgumentError('headersTimeout must be a positive integer or zero')
2131cb0ef41Sopenharmony_ci    }
2141cb0ef41Sopenharmony_ci
2151cb0ef41Sopenharmony_ci    if (bodyTimeout != null && (!Number.isInteger(bodyTimeout) || bodyTimeout < 0)) {
2161cb0ef41Sopenharmony_ci      throw new InvalidArgumentError('bodyTimeout must be a positive integer or zero')
2171cb0ef41Sopenharmony_ci    }
2181cb0ef41Sopenharmony_ci
2191cb0ef41Sopenharmony_ci    if (connect != null && typeof connect !== 'function' && typeof connect !== 'object') {
2201cb0ef41Sopenharmony_ci      throw new InvalidArgumentError('connect must be a function or an object')
2211cb0ef41Sopenharmony_ci    }
2221cb0ef41Sopenharmony_ci
2231cb0ef41Sopenharmony_ci    if (maxRedirections != null && (!Number.isInteger(maxRedirections) || maxRedirections < 0)) {
2241cb0ef41Sopenharmony_ci      throw new InvalidArgumentError('maxRedirections must be a positive number')
2251cb0ef41Sopenharmony_ci    }
2261cb0ef41Sopenharmony_ci
2271cb0ef41Sopenharmony_ci    if (maxRequestsPerClient != null && (!Number.isInteger(maxRequestsPerClient) || maxRequestsPerClient < 0)) {
2281cb0ef41Sopenharmony_ci      throw new InvalidArgumentError('maxRequestsPerClient must be a positive number')
2291cb0ef41Sopenharmony_ci    }
2301cb0ef41Sopenharmony_ci
2311cb0ef41Sopenharmony_ci    if (localAddress != null && (typeof localAddress !== 'string' || net.isIP(localAddress) === 0)) {
2321cb0ef41Sopenharmony_ci      throw new InvalidArgumentError('localAddress must be valid string IP address')
2331cb0ef41Sopenharmony_ci    }
2341cb0ef41Sopenharmony_ci
2351cb0ef41Sopenharmony_ci    if (maxResponseSize != null && (!Number.isInteger(maxResponseSize) || maxResponseSize < -1)) {
2361cb0ef41Sopenharmony_ci      throw new InvalidArgumentError('maxResponseSize must be a positive number')
2371cb0ef41Sopenharmony_ci    }
2381cb0ef41Sopenharmony_ci
2391cb0ef41Sopenharmony_ci    if (
2401cb0ef41Sopenharmony_ci      autoSelectFamilyAttemptTimeout != null &&
2411cb0ef41Sopenharmony_ci      (!Number.isInteger(autoSelectFamilyAttemptTimeout) || autoSelectFamilyAttemptTimeout < -1)
2421cb0ef41Sopenharmony_ci    ) {
2431cb0ef41Sopenharmony_ci      throw new InvalidArgumentError('autoSelectFamilyAttemptTimeout must be a positive number')
2441cb0ef41Sopenharmony_ci    }
2451cb0ef41Sopenharmony_ci
2461cb0ef41Sopenharmony_ci    // h2
2471cb0ef41Sopenharmony_ci    if (allowH2 != null && typeof allowH2 !== 'boolean') {
2481cb0ef41Sopenharmony_ci      throw new InvalidArgumentError('allowH2 must be a valid boolean value')
2491cb0ef41Sopenharmony_ci    }
2501cb0ef41Sopenharmony_ci
2511cb0ef41Sopenharmony_ci    if (maxConcurrentStreams != null && (typeof maxConcurrentStreams !== 'number' || maxConcurrentStreams < 1)) {
2521cb0ef41Sopenharmony_ci      throw new InvalidArgumentError('maxConcurrentStreams must be a possitive integer, greater than 0')
2531cb0ef41Sopenharmony_ci    }
2541cb0ef41Sopenharmony_ci
2551cb0ef41Sopenharmony_ci    if (typeof connect !== 'function') {
2561cb0ef41Sopenharmony_ci      connect = buildConnector({
2571cb0ef41Sopenharmony_ci        ...tls,
2581cb0ef41Sopenharmony_ci        maxCachedSessions,
2591cb0ef41Sopenharmony_ci        allowH2,
2601cb0ef41Sopenharmony_ci        socketPath,
2611cb0ef41Sopenharmony_ci        timeout: connectTimeout,
2621cb0ef41Sopenharmony_ci        ...(util.nodeHasAutoSelectFamily && autoSelectFamily ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : undefined),
2631cb0ef41Sopenharmony_ci        ...connect
2641cb0ef41Sopenharmony_ci      })
2651cb0ef41Sopenharmony_ci    }
2661cb0ef41Sopenharmony_ci
2671cb0ef41Sopenharmony_ci    this[kInterceptors] = interceptors && interceptors.Client && Array.isArray(interceptors.Client)
2681cb0ef41Sopenharmony_ci      ? interceptors.Client
2691cb0ef41Sopenharmony_ci      : [createRedirectInterceptor({ maxRedirections })]
2701cb0ef41Sopenharmony_ci    this[kUrl] = util.parseOrigin(url)
2711cb0ef41Sopenharmony_ci    this[kConnector] = connect
2721cb0ef41Sopenharmony_ci    this[kSocket] = null
2731cb0ef41Sopenharmony_ci    this[kPipelining] = pipelining != null ? pipelining : 1
2741cb0ef41Sopenharmony_ci    this[kMaxHeadersSize] = maxHeaderSize || http.maxHeaderSize
2751cb0ef41Sopenharmony_ci    this[kKeepAliveDefaultTimeout] = keepAliveTimeout == null ? 4e3 : keepAliveTimeout
2761cb0ef41Sopenharmony_ci    this[kKeepAliveMaxTimeout] = keepAliveMaxTimeout == null ? 600e3 : keepAliveMaxTimeout
2771cb0ef41Sopenharmony_ci    this[kKeepAliveTimeoutThreshold] = keepAliveTimeoutThreshold == null ? 1e3 : keepAliveTimeoutThreshold
2781cb0ef41Sopenharmony_ci    this[kKeepAliveTimeoutValue] = this[kKeepAliveDefaultTimeout]
2791cb0ef41Sopenharmony_ci    this[kServerName] = null
2801cb0ef41Sopenharmony_ci    this[kLocalAddress] = localAddress != null ? localAddress : null
2811cb0ef41Sopenharmony_ci    this[kResuming] = 0 // 0, idle, 1, scheduled, 2 resuming
2821cb0ef41Sopenharmony_ci    this[kNeedDrain] = 0 // 0, idle, 1, scheduled, 2 resuming
2831cb0ef41Sopenharmony_ci    this[kHostHeader] = `host: ${this[kUrl].hostname}${this[kUrl].port ? `:${this[kUrl].port}` : ''}\r\n`
2841cb0ef41Sopenharmony_ci    this[kBodyTimeout] = bodyTimeout != null ? bodyTimeout : 300e3
2851cb0ef41Sopenharmony_ci    this[kHeadersTimeout] = headersTimeout != null ? headersTimeout : 300e3
2861cb0ef41Sopenharmony_ci    this[kStrictContentLength] = strictContentLength == null ? true : strictContentLength
2871cb0ef41Sopenharmony_ci    this[kMaxRedirections] = maxRedirections
2881cb0ef41Sopenharmony_ci    this[kMaxRequests] = maxRequestsPerClient
2891cb0ef41Sopenharmony_ci    this[kClosedResolve] = null
2901cb0ef41Sopenharmony_ci    this[kMaxResponseSize] = maxResponseSize > -1 ? maxResponseSize : -1
2911cb0ef41Sopenharmony_ci    this[kHTTPConnVersion] = 'h1'
2921cb0ef41Sopenharmony_ci
2931cb0ef41Sopenharmony_ci    // HTTP/2
2941cb0ef41Sopenharmony_ci    this[kHTTP2Session] = null
2951cb0ef41Sopenharmony_ci    this[kHTTP2SessionState] = !allowH2
2961cb0ef41Sopenharmony_ci      ? null
2971cb0ef41Sopenharmony_ci      : {
2981cb0ef41Sopenharmony_ci        // streams: null, // Fixed queue of streams - For future support of `push`
2991cb0ef41Sopenharmony_ci          openStreams: 0, // Keep track of them to decide wether or not unref the session
3001cb0ef41Sopenharmony_ci          maxConcurrentStreams: maxConcurrentStreams != null ? maxConcurrentStreams : 100 // Max peerConcurrentStreams for a Node h2 server
3011cb0ef41Sopenharmony_ci        }
3021cb0ef41Sopenharmony_ci    this[kHost] = `${this[kUrl].hostname}${this[kUrl].port ? `:${this[kUrl].port}` : ''}`
3031cb0ef41Sopenharmony_ci
3041cb0ef41Sopenharmony_ci    // kQueue is built up of 3 sections separated by
3051cb0ef41Sopenharmony_ci    // the kRunningIdx and kPendingIdx indices.
3061cb0ef41Sopenharmony_ci    // |   complete   |   running   |   pending   |
3071cb0ef41Sopenharmony_ci    //                ^ kRunningIdx ^ kPendingIdx ^ kQueue.length
3081cb0ef41Sopenharmony_ci    // kRunningIdx points to the first running element.
3091cb0ef41Sopenharmony_ci    // kPendingIdx points to the first pending element.
3101cb0ef41Sopenharmony_ci    // This implements a fast queue with an amortized
3111cb0ef41Sopenharmony_ci    // time of O(1).
3121cb0ef41Sopenharmony_ci
3131cb0ef41Sopenharmony_ci    this[kQueue] = []
3141cb0ef41Sopenharmony_ci    this[kRunningIdx] = 0
3151cb0ef41Sopenharmony_ci    this[kPendingIdx] = 0
3161cb0ef41Sopenharmony_ci  }
3171cb0ef41Sopenharmony_ci
3181cb0ef41Sopenharmony_ci  get pipelining () {
3191cb0ef41Sopenharmony_ci    return this[kPipelining]
3201cb0ef41Sopenharmony_ci  }
3211cb0ef41Sopenharmony_ci
3221cb0ef41Sopenharmony_ci  set pipelining (value) {
3231cb0ef41Sopenharmony_ci    this[kPipelining] = value
3241cb0ef41Sopenharmony_ci    resume(this, true)
3251cb0ef41Sopenharmony_ci  }
3261cb0ef41Sopenharmony_ci
3271cb0ef41Sopenharmony_ci  get [kPending] () {
3281cb0ef41Sopenharmony_ci    return this[kQueue].length - this[kPendingIdx]
3291cb0ef41Sopenharmony_ci  }
3301cb0ef41Sopenharmony_ci
3311cb0ef41Sopenharmony_ci  get [kRunning] () {
3321cb0ef41Sopenharmony_ci    return this[kPendingIdx] - this[kRunningIdx]
3331cb0ef41Sopenharmony_ci  }
3341cb0ef41Sopenharmony_ci
3351cb0ef41Sopenharmony_ci  get [kSize] () {
3361cb0ef41Sopenharmony_ci    return this[kQueue].length - this[kRunningIdx]
3371cb0ef41Sopenharmony_ci  }
3381cb0ef41Sopenharmony_ci
3391cb0ef41Sopenharmony_ci  get [kConnected] () {
3401cb0ef41Sopenharmony_ci    return !!this[kSocket] && !this[kConnecting] && !this[kSocket].destroyed
3411cb0ef41Sopenharmony_ci  }
3421cb0ef41Sopenharmony_ci
3431cb0ef41Sopenharmony_ci  get [kBusy] () {
3441cb0ef41Sopenharmony_ci    const socket = this[kSocket]
3451cb0ef41Sopenharmony_ci    return (
3461cb0ef41Sopenharmony_ci      (socket && (socket[kReset] || socket[kWriting] || socket[kBlocking])) ||
3471cb0ef41Sopenharmony_ci      (this[kSize] >= (this[kPipelining] || 1)) ||
3481cb0ef41Sopenharmony_ci      this[kPending] > 0
3491cb0ef41Sopenharmony_ci    )
3501cb0ef41Sopenharmony_ci  }
3511cb0ef41Sopenharmony_ci
3521cb0ef41Sopenharmony_ci  /* istanbul ignore: only used for test */
3531cb0ef41Sopenharmony_ci  [kConnect] (cb) {
3541cb0ef41Sopenharmony_ci    connect(this)
3551cb0ef41Sopenharmony_ci    this.once('connect', cb)
3561cb0ef41Sopenharmony_ci  }
3571cb0ef41Sopenharmony_ci
3581cb0ef41Sopenharmony_ci  [kDispatch] (opts, handler) {
3591cb0ef41Sopenharmony_ci    const origin = opts.origin || this[kUrl].origin
3601cb0ef41Sopenharmony_ci
3611cb0ef41Sopenharmony_ci    const request = this[kHTTPConnVersion] === 'h2'
3621cb0ef41Sopenharmony_ci      ? Request[kHTTP2BuildRequest](origin, opts, handler)
3631cb0ef41Sopenharmony_ci      : Request[kHTTP1BuildRequest](origin, opts, handler)
3641cb0ef41Sopenharmony_ci
3651cb0ef41Sopenharmony_ci    this[kQueue].push(request)
3661cb0ef41Sopenharmony_ci    if (this[kResuming]) {
3671cb0ef41Sopenharmony_ci      // Do nothing.
3681cb0ef41Sopenharmony_ci    } else if (util.bodyLength(request.body) == null && util.isIterable(request.body)) {
3691cb0ef41Sopenharmony_ci      // Wait a tick in case stream/iterator is ended in the same tick.
3701cb0ef41Sopenharmony_ci      this[kResuming] = 1
3711cb0ef41Sopenharmony_ci      process.nextTick(resume, this)
3721cb0ef41Sopenharmony_ci    } else {
3731cb0ef41Sopenharmony_ci      resume(this, true)
3741cb0ef41Sopenharmony_ci    }
3751cb0ef41Sopenharmony_ci
3761cb0ef41Sopenharmony_ci    if (this[kResuming] && this[kNeedDrain] !== 2 && this[kBusy]) {
3771cb0ef41Sopenharmony_ci      this[kNeedDrain] = 2
3781cb0ef41Sopenharmony_ci    }
3791cb0ef41Sopenharmony_ci
3801cb0ef41Sopenharmony_ci    return this[kNeedDrain] < 2
3811cb0ef41Sopenharmony_ci  }
3821cb0ef41Sopenharmony_ci
3831cb0ef41Sopenharmony_ci  async [kClose] () {
3841cb0ef41Sopenharmony_ci    // TODO: for H2 we need to gracefully flush the remaining enqueued
3851cb0ef41Sopenharmony_ci    // request and close each stream.
3861cb0ef41Sopenharmony_ci    return new Promise((resolve) => {
3871cb0ef41Sopenharmony_ci      if (!this[kSize]) {
3881cb0ef41Sopenharmony_ci        resolve(null)
3891cb0ef41Sopenharmony_ci      } else {
3901cb0ef41Sopenharmony_ci        this[kClosedResolve] = resolve
3911cb0ef41Sopenharmony_ci      }
3921cb0ef41Sopenharmony_ci    })
3931cb0ef41Sopenharmony_ci  }
3941cb0ef41Sopenharmony_ci
3951cb0ef41Sopenharmony_ci  async [kDestroy] (err) {
3961cb0ef41Sopenharmony_ci    return new Promise((resolve) => {
3971cb0ef41Sopenharmony_ci      const requests = this[kQueue].splice(this[kPendingIdx])
3981cb0ef41Sopenharmony_ci      for (let i = 0; i < requests.length; i++) {
3991cb0ef41Sopenharmony_ci        const request = requests[i]
4001cb0ef41Sopenharmony_ci        errorRequest(this, request, err)
4011cb0ef41Sopenharmony_ci      }
4021cb0ef41Sopenharmony_ci
4031cb0ef41Sopenharmony_ci      const callback = () => {
4041cb0ef41Sopenharmony_ci        if (this[kClosedResolve]) {
4051cb0ef41Sopenharmony_ci          // TODO (fix): Should we error here with ClientDestroyedError?
4061cb0ef41Sopenharmony_ci          this[kClosedResolve]()
4071cb0ef41Sopenharmony_ci          this[kClosedResolve] = null
4081cb0ef41Sopenharmony_ci        }
4091cb0ef41Sopenharmony_ci        resolve()
4101cb0ef41Sopenharmony_ci      }
4111cb0ef41Sopenharmony_ci
4121cb0ef41Sopenharmony_ci      if (this[kHTTP2Session] != null) {
4131cb0ef41Sopenharmony_ci        util.destroy(this[kHTTP2Session], err)
4141cb0ef41Sopenharmony_ci        this[kHTTP2Session] = null
4151cb0ef41Sopenharmony_ci        this[kHTTP2SessionState] = null
4161cb0ef41Sopenharmony_ci      }
4171cb0ef41Sopenharmony_ci
4181cb0ef41Sopenharmony_ci      if (!this[kSocket]) {
4191cb0ef41Sopenharmony_ci        queueMicrotask(callback)
4201cb0ef41Sopenharmony_ci      } else {
4211cb0ef41Sopenharmony_ci        util.destroy(this[kSocket].on('close', callback), err)
4221cb0ef41Sopenharmony_ci      }
4231cb0ef41Sopenharmony_ci
4241cb0ef41Sopenharmony_ci      resume(this)
4251cb0ef41Sopenharmony_ci    })
4261cb0ef41Sopenharmony_ci  }
4271cb0ef41Sopenharmony_ci}
4281cb0ef41Sopenharmony_ci
4291cb0ef41Sopenharmony_cifunction onHttp2SessionError (err) {
4301cb0ef41Sopenharmony_ci  assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID')
4311cb0ef41Sopenharmony_ci
4321cb0ef41Sopenharmony_ci  this[kSocket][kError] = err
4331cb0ef41Sopenharmony_ci
4341cb0ef41Sopenharmony_ci  onError(this[kClient], err)
4351cb0ef41Sopenharmony_ci}
4361cb0ef41Sopenharmony_ci
4371cb0ef41Sopenharmony_cifunction onHttp2FrameError (type, code, id) {
4381cb0ef41Sopenharmony_ci  const err = new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`)
4391cb0ef41Sopenharmony_ci
4401cb0ef41Sopenharmony_ci  if (id === 0) {
4411cb0ef41Sopenharmony_ci    this[kSocket][kError] = err
4421cb0ef41Sopenharmony_ci    onError(this[kClient], err)
4431cb0ef41Sopenharmony_ci  }
4441cb0ef41Sopenharmony_ci}
4451cb0ef41Sopenharmony_ci
4461cb0ef41Sopenharmony_cifunction onHttp2SessionEnd () {
4471cb0ef41Sopenharmony_ci  util.destroy(this, new SocketError('other side closed'))
4481cb0ef41Sopenharmony_ci  util.destroy(this[kSocket], new SocketError('other side closed'))
4491cb0ef41Sopenharmony_ci}
4501cb0ef41Sopenharmony_ci
4511cb0ef41Sopenharmony_cifunction onHTTP2GoAway (code) {
4521cb0ef41Sopenharmony_ci  const client = this[kClient]
4531cb0ef41Sopenharmony_ci  const err = new InformationalError(`HTTP/2: "GOAWAY" frame received with code ${code}`)
4541cb0ef41Sopenharmony_ci  client[kSocket] = null
4551cb0ef41Sopenharmony_ci  client[kHTTP2Session] = null
4561cb0ef41Sopenharmony_ci
4571cb0ef41Sopenharmony_ci  if (client.destroyed) {
4581cb0ef41Sopenharmony_ci    assert(this[kPending] === 0)
4591cb0ef41Sopenharmony_ci
4601cb0ef41Sopenharmony_ci    // Fail entire queue.
4611cb0ef41Sopenharmony_ci    const requests = client[kQueue].splice(client[kRunningIdx])
4621cb0ef41Sopenharmony_ci    for (let i = 0; i < requests.length; i++) {
4631cb0ef41Sopenharmony_ci      const request = requests[i]
4641cb0ef41Sopenharmony_ci      errorRequest(this, request, err)
4651cb0ef41Sopenharmony_ci    }
4661cb0ef41Sopenharmony_ci  } else if (client[kRunning] > 0) {
4671cb0ef41Sopenharmony_ci    // Fail head of pipeline.
4681cb0ef41Sopenharmony_ci    const request = client[kQueue][client[kRunningIdx]]
4691cb0ef41Sopenharmony_ci    client[kQueue][client[kRunningIdx]++] = null
4701cb0ef41Sopenharmony_ci
4711cb0ef41Sopenharmony_ci    errorRequest(client, request, err)
4721cb0ef41Sopenharmony_ci  }
4731cb0ef41Sopenharmony_ci
4741cb0ef41Sopenharmony_ci  client[kPendingIdx] = client[kRunningIdx]
4751cb0ef41Sopenharmony_ci
4761cb0ef41Sopenharmony_ci  assert(client[kRunning] === 0)
4771cb0ef41Sopenharmony_ci
4781cb0ef41Sopenharmony_ci  client.emit('disconnect',
4791cb0ef41Sopenharmony_ci    client[kUrl],
4801cb0ef41Sopenharmony_ci    [client],
4811cb0ef41Sopenharmony_ci    err
4821cb0ef41Sopenharmony_ci  )
4831cb0ef41Sopenharmony_ci
4841cb0ef41Sopenharmony_ci  resume(client)
4851cb0ef41Sopenharmony_ci}
4861cb0ef41Sopenharmony_ci
4871cb0ef41Sopenharmony_ciconst constants = require('./llhttp/constants')
4881cb0ef41Sopenharmony_ciconst createRedirectInterceptor = require('./interceptor/redirectInterceptor')
4891cb0ef41Sopenharmony_ciconst EMPTY_BUF = Buffer.alloc(0)
4901cb0ef41Sopenharmony_ci
4911cb0ef41Sopenharmony_ciasync function lazyllhttp () {
4921cb0ef41Sopenharmony_ci  const llhttpWasmData = process.env.JEST_WORKER_ID ? require('./llhttp/llhttp-wasm.js') : undefined
4931cb0ef41Sopenharmony_ci
4941cb0ef41Sopenharmony_ci  let mod
4951cb0ef41Sopenharmony_ci  try {
4961cb0ef41Sopenharmony_ci    mod = await WebAssembly.compile(Buffer.from(require('./llhttp/llhttp_simd-wasm.js'), 'base64'))
4971cb0ef41Sopenharmony_ci  } catch (e) {
4981cb0ef41Sopenharmony_ci    /* istanbul ignore next */
4991cb0ef41Sopenharmony_ci
5001cb0ef41Sopenharmony_ci    // We could check if the error was caused by the simd option not
5011cb0ef41Sopenharmony_ci    // being enabled, but the occurring of this other error
5021cb0ef41Sopenharmony_ci    // * https://github.com/emscripten-core/emscripten/issues/11495
5031cb0ef41Sopenharmony_ci    // got me to remove that check to avoid breaking Node 12.
5041cb0ef41Sopenharmony_ci    mod = await WebAssembly.compile(Buffer.from(llhttpWasmData || require('./llhttp/llhttp-wasm.js'), 'base64'))
5051cb0ef41Sopenharmony_ci  }
5061cb0ef41Sopenharmony_ci
5071cb0ef41Sopenharmony_ci  return await WebAssembly.instantiate(mod, {
5081cb0ef41Sopenharmony_ci    env: {
5091cb0ef41Sopenharmony_ci      /* eslint-disable camelcase */
5101cb0ef41Sopenharmony_ci
5111cb0ef41Sopenharmony_ci      wasm_on_url: (p, at, len) => {
5121cb0ef41Sopenharmony_ci        /* istanbul ignore next */
5131cb0ef41Sopenharmony_ci        return 0
5141cb0ef41Sopenharmony_ci      },
5151cb0ef41Sopenharmony_ci      wasm_on_status: (p, at, len) => {
5161cb0ef41Sopenharmony_ci        assert.strictEqual(currentParser.ptr, p)
5171cb0ef41Sopenharmony_ci        const start = at - currentBufferPtr + currentBufferRef.byteOffset
5181cb0ef41Sopenharmony_ci        return currentParser.onStatus(new FastBuffer(currentBufferRef.buffer, start, len)) || 0
5191cb0ef41Sopenharmony_ci      },
5201cb0ef41Sopenharmony_ci      wasm_on_message_begin: (p) => {
5211cb0ef41Sopenharmony_ci        assert.strictEqual(currentParser.ptr, p)
5221cb0ef41Sopenharmony_ci        return currentParser.onMessageBegin() || 0
5231cb0ef41Sopenharmony_ci      },
5241cb0ef41Sopenharmony_ci      wasm_on_header_field: (p, at, len) => {
5251cb0ef41Sopenharmony_ci        assert.strictEqual(currentParser.ptr, p)
5261cb0ef41Sopenharmony_ci        const start = at - currentBufferPtr + currentBufferRef.byteOffset
5271cb0ef41Sopenharmony_ci        return currentParser.onHeaderField(new FastBuffer(currentBufferRef.buffer, start, len)) || 0
5281cb0ef41Sopenharmony_ci      },
5291cb0ef41Sopenharmony_ci      wasm_on_header_value: (p, at, len) => {
5301cb0ef41Sopenharmony_ci        assert.strictEqual(currentParser.ptr, p)
5311cb0ef41Sopenharmony_ci        const start = at - currentBufferPtr + currentBufferRef.byteOffset
5321cb0ef41Sopenharmony_ci        return currentParser.onHeaderValue(new FastBuffer(currentBufferRef.buffer, start, len)) || 0
5331cb0ef41Sopenharmony_ci      },
5341cb0ef41Sopenharmony_ci      wasm_on_headers_complete: (p, statusCode, upgrade, shouldKeepAlive) => {
5351cb0ef41Sopenharmony_ci        assert.strictEqual(currentParser.ptr, p)
5361cb0ef41Sopenharmony_ci        return currentParser.onHeadersComplete(statusCode, Boolean(upgrade), Boolean(shouldKeepAlive)) || 0
5371cb0ef41Sopenharmony_ci      },
5381cb0ef41Sopenharmony_ci      wasm_on_body: (p, at, len) => {
5391cb0ef41Sopenharmony_ci        assert.strictEqual(currentParser.ptr, p)
5401cb0ef41Sopenharmony_ci        const start = at - currentBufferPtr + currentBufferRef.byteOffset
5411cb0ef41Sopenharmony_ci        return currentParser.onBody(new FastBuffer(currentBufferRef.buffer, start, len)) || 0
5421cb0ef41Sopenharmony_ci      },
5431cb0ef41Sopenharmony_ci      wasm_on_message_complete: (p) => {
5441cb0ef41Sopenharmony_ci        assert.strictEqual(currentParser.ptr, p)
5451cb0ef41Sopenharmony_ci        return currentParser.onMessageComplete() || 0
5461cb0ef41Sopenharmony_ci      }
5471cb0ef41Sopenharmony_ci
5481cb0ef41Sopenharmony_ci      /* eslint-enable camelcase */
5491cb0ef41Sopenharmony_ci    }
5501cb0ef41Sopenharmony_ci  })
5511cb0ef41Sopenharmony_ci}
5521cb0ef41Sopenharmony_ci
5531cb0ef41Sopenharmony_cilet llhttpInstance = null
5541cb0ef41Sopenharmony_cilet llhttpPromise = lazyllhttp()
5551cb0ef41Sopenharmony_cillhttpPromise.catch()
5561cb0ef41Sopenharmony_ci
5571cb0ef41Sopenharmony_cilet currentParser = null
5581cb0ef41Sopenharmony_cilet currentBufferRef = null
5591cb0ef41Sopenharmony_cilet currentBufferSize = 0
5601cb0ef41Sopenharmony_cilet currentBufferPtr = null
5611cb0ef41Sopenharmony_ci
5621cb0ef41Sopenharmony_ciconst TIMEOUT_HEADERS = 1
5631cb0ef41Sopenharmony_ciconst TIMEOUT_BODY = 2
5641cb0ef41Sopenharmony_ciconst TIMEOUT_IDLE = 3
5651cb0ef41Sopenharmony_ci
5661cb0ef41Sopenharmony_ciclass Parser {
5671cb0ef41Sopenharmony_ci  constructor (client, socket, { exports }) {
5681cb0ef41Sopenharmony_ci    assert(Number.isFinite(client[kMaxHeadersSize]) && client[kMaxHeadersSize] > 0)
5691cb0ef41Sopenharmony_ci
5701cb0ef41Sopenharmony_ci    this.llhttp = exports
5711cb0ef41Sopenharmony_ci    this.ptr = this.llhttp.llhttp_alloc(constants.TYPE.RESPONSE)
5721cb0ef41Sopenharmony_ci    this.client = client
5731cb0ef41Sopenharmony_ci    this.socket = socket
5741cb0ef41Sopenharmony_ci    this.timeout = null
5751cb0ef41Sopenharmony_ci    this.timeoutValue = null
5761cb0ef41Sopenharmony_ci    this.timeoutType = null
5771cb0ef41Sopenharmony_ci    this.statusCode = null
5781cb0ef41Sopenharmony_ci    this.statusText = ''
5791cb0ef41Sopenharmony_ci    this.upgrade = false
5801cb0ef41Sopenharmony_ci    this.headers = []
5811cb0ef41Sopenharmony_ci    this.headersSize = 0
5821cb0ef41Sopenharmony_ci    this.headersMaxSize = client[kMaxHeadersSize]
5831cb0ef41Sopenharmony_ci    this.shouldKeepAlive = false
5841cb0ef41Sopenharmony_ci    this.paused = false
5851cb0ef41Sopenharmony_ci    this.resume = this.resume.bind(this)
5861cb0ef41Sopenharmony_ci
5871cb0ef41Sopenharmony_ci    this.bytesRead = 0
5881cb0ef41Sopenharmony_ci
5891cb0ef41Sopenharmony_ci    this.keepAlive = ''
5901cb0ef41Sopenharmony_ci    this.contentLength = ''
5911cb0ef41Sopenharmony_ci    this.connection = ''
5921cb0ef41Sopenharmony_ci    this.maxResponseSize = client[kMaxResponseSize]
5931cb0ef41Sopenharmony_ci  }
5941cb0ef41Sopenharmony_ci
5951cb0ef41Sopenharmony_ci  setTimeout (value, type) {
5961cb0ef41Sopenharmony_ci    this.timeoutType = type
5971cb0ef41Sopenharmony_ci    if (value !== this.timeoutValue) {
5981cb0ef41Sopenharmony_ci      timers.clearTimeout(this.timeout)
5991cb0ef41Sopenharmony_ci      if (value) {
6001cb0ef41Sopenharmony_ci        this.timeout = timers.setTimeout(onParserTimeout, value, this)
6011cb0ef41Sopenharmony_ci        // istanbul ignore else: only for jest
6021cb0ef41Sopenharmony_ci        if (this.timeout.unref) {
6031cb0ef41Sopenharmony_ci          this.timeout.unref()
6041cb0ef41Sopenharmony_ci        }
6051cb0ef41Sopenharmony_ci      } else {
6061cb0ef41Sopenharmony_ci        this.timeout = null
6071cb0ef41Sopenharmony_ci      }
6081cb0ef41Sopenharmony_ci      this.timeoutValue = value
6091cb0ef41Sopenharmony_ci    } else if (this.timeout) {
6101cb0ef41Sopenharmony_ci      // istanbul ignore else: only for jest
6111cb0ef41Sopenharmony_ci      if (this.timeout.refresh) {
6121cb0ef41Sopenharmony_ci        this.timeout.refresh()
6131cb0ef41Sopenharmony_ci      }
6141cb0ef41Sopenharmony_ci    }
6151cb0ef41Sopenharmony_ci  }
6161cb0ef41Sopenharmony_ci
6171cb0ef41Sopenharmony_ci  resume () {
6181cb0ef41Sopenharmony_ci    if (this.socket.destroyed || !this.paused) {
6191cb0ef41Sopenharmony_ci      return
6201cb0ef41Sopenharmony_ci    }
6211cb0ef41Sopenharmony_ci
6221cb0ef41Sopenharmony_ci    assert(this.ptr != null)
6231cb0ef41Sopenharmony_ci    assert(currentParser == null)
6241cb0ef41Sopenharmony_ci
6251cb0ef41Sopenharmony_ci    this.llhttp.llhttp_resume(this.ptr)
6261cb0ef41Sopenharmony_ci
6271cb0ef41Sopenharmony_ci    assert(this.timeoutType === TIMEOUT_BODY)
6281cb0ef41Sopenharmony_ci    if (this.timeout) {
6291cb0ef41Sopenharmony_ci      // istanbul ignore else: only for jest
6301cb0ef41Sopenharmony_ci      if (this.timeout.refresh) {
6311cb0ef41Sopenharmony_ci        this.timeout.refresh()
6321cb0ef41Sopenharmony_ci      }
6331cb0ef41Sopenharmony_ci    }
6341cb0ef41Sopenharmony_ci
6351cb0ef41Sopenharmony_ci    this.paused = false
6361cb0ef41Sopenharmony_ci    this.execute(this.socket.read() || EMPTY_BUF) // Flush parser.
6371cb0ef41Sopenharmony_ci    this.readMore()
6381cb0ef41Sopenharmony_ci  }
6391cb0ef41Sopenharmony_ci
6401cb0ef41Sopenharmony_ci  readMore () {
6411cb0ef41Sopenharmony_ci    while (!this.paused && this.ptr) {
6421cb0ef41Sopenharmony_ci      const chunk = this.socket.read()
6431cb0ef41Sopenharmony_ci      if (chunk === null) {
6441cb0ef41Sopenharmony_ci        break
6451cb0ef41Sopenharmony_ci      }
6461cb0ef41Sopenharmony_ci      this.execute(chunk)
6471cb0ef41Sopenharmony_ci    }
6481cb0ef41Sopenharmony_ci  }
6491cb0ef41Sopenharmony_ci
6501cb0ef41Sopenharmony_ci  execute (data) {
6511cb0ef41Sopenharmony_ci    assert(this.ptr != null)
6521cb0ef41Sopenharmony_ci    assert(currentParser == null)
6531cb0ef41Sopenharmony_ci    assert(!this.paused)
6541cb0ef41Sopenharmony_ci
6551cb0ef41Sopenharmony_ci    const { socket, llhttp } = this
6561cb0ef41Sopenharmony_ci
6571cb0ef41Sopenharmony_ci    if (data.length > currentBufferSize) {
6581cb0ef41Sopenharmony_ci      if (currentBufferPtr) {
6591cb0ef41Sopenharmony_ci        llhttp.free(currentBufferPtr)
6601cb0ef41Sopenharmony_ci      }
6611cb0ef41Sopenharmony_ci      currentBufferSize = Math.ceil(data.length / 4096) * 4096
6621cb0ef41Sopenharmony_ci      currentBufferPtr = llhttp.malloc(currentBufferSize)
6631cb0ef41Sopenharmony_ci    }
6641cb0ef41Sopenharmony_ci
6651cb0ef41Sopenharmony_ci    new Uint8Array(llhttp.memory.buffer, currentBufferPtr, currentBufferSize).set(data)
6661cb0ef41Sopenharmony_ci
6671cb0ef41Sopenharmony_ci    // Call `execute` on the wasm parser.
6681cb0ef41Sopenharmony_ci    // We pass the `llhttp_parser` pointer address, the pointer address of buffer view data,
6691cb0ef41Sopenharmony_ci    // and finally the length of bytes to parse.
6701cb0ef41Sopenharmony_ci    // The return value is an error code or `constants.ERROR.OK`.
6711cb0ef41Sopenharmony_ci    try {
6721cb0ef41Sopenharmony_ci      let ret
6731cb0ef41Sopenharmony_ci
6741cb0ef41Sopenharmony_ci      try {
6751cb0ef41Sopenharmony_ci        currentBufferRef = data
6761cb0ef41Sopenharmony_ci        currentParser = this
6771cb0ef41Sopenharmony_ci        ret = llhttp.llhttp_execute(this.ptr, currentBufferPtr, data.length)
6781cb0ef41Sopenharmony_ci        /* eslint-disable-next-line no-useless-catch */
6791cb0ef41Sopenharmony_ci      } catch (err) {
6801cb0ef41Sopenharmony_ci        /* istanbul ignore next: difficult to make a test case for */
6811cb0ef41Sopenharmony_ci        throw err
6821cb0ef41Sopenharmony_ci      } finally {
6831cb0ef41Sopenharmony_ci        currentParser = null
6841cb0ef41Sopenharmony_ci        currentBufferRef = null
6851cb0ef41Sopenharmony_ci      }
6861cb0ef41Sopenharmony_ci
6871cb0ef41Sopenharmony_ci      const offset = llhttp.llhttp_get_error_pos(this.ptr) - currentBufferPtr
6881cb0ef41Sopenharmony_ci
6891cb0ef41Sopenharmony_ci      if (ret === constants.ERROR.PAUSED_UPGRADE) {
6901cb0ef41Sopenharmony_ci        this.onUpgrade(data.slice(offset))
6911cb0ef41Sopenharmony_ci      } else if (ret === constants.ERROR.PAUSED) {
6921cb0ef41Sopenharmony_ci        this.paused = true
6931cb0ef41Sopenharmony_ci        socket.unshift(data.slice(offset))
6941cb0ef41Sopenharmony_ci      } else if (ret !== constants.ERROR.OK) {
6951cb0ef41Sopenharmony_ci        const ptr = llhttp.llhttp_get_error_reason(this.ptr)
6961cb0ef41Sopenharmony_ci        let message = ''
6971cb0ef41Sopenharmony_ci        /* istanbul ignore else: difficult to make a test case for */
6981cb0ef41Sopenharmony_ci        if (ptr) {
6991cb0ef41Sopenharmony_ci          const len = new Uint8Array(llhttp.memory.buffer, ptr).indexOf(0)
7001cb0ef41Sopenharmony_ci          message =
7011cb0ef41Sopenharmony_ci            'Response does not match the HTTP/1.1 protocol (' +
7021cb0ef41Sopenharmony_ci            Buffer.from(llhttp.memory.buffer, ptr, len).toString() +
7031cb0ef41Sopenharmony_ci            ')'
7041cb0ef41Sopenharmony_ci        }
7051cb0ef41Sopenharmony_ci        throw new HTTPParserError(message, constants.ERROR[ret], data.slice(offset))
7061cb0ef41Sopenharmony_ci      }
7071cb0ef41Sopenharmony_ci    } catch (err) {
7081cb0ef41Sopenharmony_ci      util.destroy(socket, err)
7091cb0ef41Sopenharmony_ci    }
7101cb0ef41Sopenharmony_ci  }
7111cb0ef41Sopenharmony_ci
7121cb0ef41Sopenharmony_ci  destroy () {
7131cb0ef41Sopenharmony_ci    assert(this.ptr != null)
7141cb0ef41Sopenharmony_ci    assert(currentParser == null)
7151cb0ef41Sopenharmony_ci
7161cb0ef41Sopenharmony_ci    this.llhttp.llhttp_free(this.ptr)
7171cb0ef41Sopenharmony_ci    this.ptr = null
7181cb0ef41Sopenharmony_ci
7191cb0ef41Sopenharmony_ci    timers.clearTimeout(this.timeout)
7201cb0ef41Sopenharmony_ci    this.timeout = null
7211cb0ef41Sopenharmony_ci    this.timeoutValue = null
7221cb0ef41Sopenharmony_ci    this.timeoutType = null
7231cb0ef41Sopenharmony_ci
7241cb0ef41Sopenharmony_ci    this.paused = false
7251cb0ef41Sopenharmony_ci  }
7261cb0ef41Sopenharmony_ci
7271cb0ef41Sopenharmony_ci  onStatus (buf) {
7281cb0ef41Sopenharmony_ci    this.statusText = buf.toString()
7291cb0ef41Sopenharmony_ci  }
7301cb0ef41Sopenharmony_ci
7311cb0ef41Sopenharmony_ci  onMessageBegin () {
7321cb0ef41Sopenharmony_ci    const { socket, client } = this
7331cb0ef41Sopenharmony_ci
7341cb0ef41Sopenharmony_ci    /* istanbul ignore next: difficult to make a test case for */
7351cb0ef41Sopenharmony_ci    if (socket.destroyed) {
7361cb0ef41Sopenharmony_ci      return -1
7371cb0ef41Sopenharmony_ci    }
7381cb0ef41Sopenharmony_ci
7391cb0ef41Sopenharmony_ci    const request = client[kQueue][client[kRunningIdx]]
7401cb0ef41Sopenharmony_ci    if (!request) {
7411cb0ef41Sopenharmony_ci      return -1
7421cb0ef41Sopenharmony_ci    }
7431cb0ef41Sopenharmony_ci  }
7441cb0ef41Sopenharmony_ci
7451cb0ef41Sopenharmony_ci  onHeaderField (buf) {
7461cb0ef41Sopenharmony_ci    const len = this.headers.length
7471cb0ef41Sopenharmony_ci
7481cb0ef41Sopenharmony_ci    if ((len & 1) === 0) {
7491cb0ef41Sopenharmony_ci      this.headers.push(buf)
7501cb0ef41Sopenharmony_ci    } else {
7511cb0ef41Sopenharmony_ci      this.headers[len - 1] = Buffer.concat([this.headers[len - 1], buf])
7521cb0ef41Sopenharmony_ci    }
7531cb0ef41Sopenharmony_ci
7541cb0ef41Sopenharmony_ci    this.trackHeader(buf.length)
7551cb0ef41Sopenharmony_ci  }
7561cb0ef41Sopenharmony_ci
7571cb0ef41Sopenharmony_ci  onHeaderValue (buf) {
7581cb0ef41Sopenharmony_ci    let len = this.headers.length
7591cb0ef41Sopenharmony_ci
7601cb0ef41Sopenharmony_ci    if ((len & 1) === 1) {
7611cb0ef41Sopenharmony_ci      this.headers.push(buf)
7621cb0ef41Sopenharmony_ci      len += 1
7631cb0ef41Sopenharmony_ci    } else {
7641cb0ef41Sopenharmony_ci      this.headers[len - 1] = Buffer.concat([this.headers[len - 1], buf])
7651cb0ef41Sopenharmony_ci    }
7661cb0ef41Sopenharmony_ci
7671cb0ef41Sopenharmony_ci    const key = this.headers[len - 2]
7681cb0ef41Sopenharmony_ci    if (key.length === 10 && key.toString().toLowerCase() === 'keep-alive') {
7691cb0ef41Sopenharmony_ci      this.keepAlive += buf.toString()
7701cb0ef41Sopenharmony_ci    } else if (key.length === 10 && key.toString().toLowerCase() === 'connection') {
7711cb0ef41Sopenharmony_ci      this.connection += buf.toString()
7721cb0ef41Sopenharmony_ci    } else if (key.length === 14 && key.toString().toLowerCase() === 'content-length') {
7731cb0ef41Sopenharmony_ci      this.contentLength += buf.toString()
7741cb0ef41Sopenharmony_ci    }
7751cb0ef41Sopenharmony_ci
7761cb0ef41Sopenharmony_ci    this.trackHeader(buf.length)
7771cb0ef41Sopenharmony_ci  }
7781cb0ef41Sopenharmony_ci
7791cb0ef41Sopenharmony_ci  trackHeader (len) {
7801cb0ef41Sopenharmony_ci    this.headersSize += len
7811cb0ef41Sopenharmony_ci    if (this.headersSize >= this.headersMaxSize) {
7821cb0ef41Sopenharmony_ci      util.destroy(this.socket, new HeadersOverflowError())
7831cb0ef41Sopenharmony_ci    }
7841cb0ef41Sopenharmony_ci  }
7851cb0ef41Sopenharmony_ci
7861cb0ef41Sopenharmony_ci  onUpgrade (head) {
7871cb0ef41Sopenharmony_ci    const { upgrade, client, socket, headers, statusCode } = this
7881cb0ef41Sopenharmony_ci
7891cb0ef41Sopenharmony_ci    assert(upgrade)
7901cb0ef41Sopenharmony_ci
7911cb0ef41Sopenharmony_ci    const request = client[kQueue][client[kRunningIdx]]
7921cb0ef41Sopenharmony_ci    assert(request)
7931cb0ef41Sopenharmony_ci
7941cb0ef41Sopenharmony_ci    assert(!socket.destroyed)
7951cb0ef41Sopenharmony_ci    assert(socket === client[kSocket])
7961cb0ef41Sopenharmony_ci    assert(!this.paused)
7971cb0ef41Sopenharmony_ci    assert(request.upgrade || request.method === 'CONNECT')
7981cb0ef41Sopenharmony_ci
7991cb0ef41Sopenharmony_ci    this.statusCode = null
8001cb0ef41Sopenharmony_ci    this.statusText = ''
8011cb0ef41Sopenharmony_ci    this.shouldKeepAlive = null
8021cb0ef41Sopenharmony_ci
8031cb0ef41Sopenharmony_ci    assert(this.headers.length % 2 === 0)
8041cb0ef41Sopenharmony_ci    this.headers = []
8051cb0ef41Sopenharmony_ci    this.headersSize = 0
8061cb0ef41Sopenharmony_ci
8071cb0ef41Sopenharmony_ci    socket.unshift(head)
8081cb0ef41Sopenharmony_ci
8091cb0ef41Sopenharmony_ci    socket[kParser].destroy()
8101cb0ef41Sopenharmony_ci    socket[kParser] = null
8111cb0ef41Sopenharmony_ci
8121cb0ef41Sopenharmony_ci    socket[kClient] = null
8131cb0ef41Sopenharmony_ci    socket[kError] = null
8141cb0ef41Sopenharmony_ci    socket
8151cb0ef41Sopenharmony_ci      .removeListener('error', onSocketError)
8161cb0ef41Sopenharmony_ci      .removeListener('readable', onSocketReadable)
8171cb0ef41Sopenharmony_ci      .removeListener('end', onSocketEnd)
8181cb0ef41Sopenharmony_ci      .removeListener('close', onSocketClose)
8191cb0ef41Sopenharmony_ci
8201cb0ef41Sopenharmony_ci    client[kSocket] = null
8211cb0ef41Sopenharmony_ci    client[kQueue][client[kRunningIdx]++] = null
8221cb0ef41Sopenharmony_ci    client.emit('disconnect', client[kUrl], [client], new InformationalError('upgrade'))
8231cb0ef41Sopenharmony_ci
8241cb0ef41Sopenharmony_ci    try {
8251cb0ef41Sopenharmony_ci      request.onUpgrade(statusCode, headers, socket)
8261cb0ef41Sopenharmony_ci    } catch (err) {
8271cb0ef41Sopenharmony_ci      util.destroy(socket, err)
8281cb0ef41Sopenharmony_ci    }
8291cb0ef41Sopenharmony_ci
8301cb0ef41Sopenharmony_ci    resume(client)
8311cb0ef41Sopenharmony_ci  }
8321cb0ef41Sopenharmony_ci
8331cb0ef41Sopenharmony_ci  onHeadersComplete (statusCode, upgrade, shouldKeepAlive) {
8341cb0ef41Sopenharmony_ci    const { client, socket, headers, statusText } = this
8351cb0ef41Sopenharmony_ci
8361cb0ef41Sopenharmony_ci    /* istanbul ignore next: difficult to make a test case for */
8371cb0ef41Sopenharmony_ci    if (socket.destroyed) {
8381cb0ef41Sopenharmony_ci      return -1
8391cb0ef41Sopenharmony_ci    }
8401cb0ef41Sopenharmony_ci
8411cb0ef41Sopenharmony_ci    const request = client[kQueue][client[kRunningIdx]]
8421cb0ef41Sopenharmony_ci
8431cb0ef41Sopenharmony_ci    /* istanbul ignore next: difficult to make a test case for */
8441cb0ef41Sopenharmony_ci    if (!request) {
8451cb0ef41Sopenharmony_ci      return -1
8461cb0ef41Sopenharmony_ci    }
8471cb0ef41Sopenharmony_ci
8481cb0ef41Sopenharmony_ci    assert(!this.upgrade)
8491cb0ef41Sopenharmony_ci    assert(this.statusCode < 200)
8501cb0ef41Sopenharmony_ci
8511cb0ef41Sopenharmony_ci    if (statusCode === 100) {
8521cb0ef41Sopenharmony_ci      util.destroy(socket, new SocketError('bad response', util.getSocketInfo(socket)))
8531cb0ef41Sopenharmony_ci      return -1
8541cb0ef41Sopenharmony_ci    }
8551cb0ef41Sopenharmony_ci
8561cb0ef41Sopenharmony_ci    /* this can only happen if server is misbehaving */
8571cb0ef41Sopenharmony_ci    if (upgrade && !request.upgrade) {
8581cb0ef41Sopenharmony_ci      util.destroy(socket, new SocketError('bad upgrade', util.getSocketInfo(socket)))
8591cb0ef41Sopenharmony_ci      return -1
8601cb0ef41Sopenharmony_ci    }
8611cb0ef41Sopenharmony_ci
8621cb0ef41Sopenharmony_ci    assert.strictEqual(this.timeoutType, TIMEOUT_HEADERS)
8631cb0ef41Sopenharmony_ci
8641cb0ef41Sopenharmony_ci    this.statusCode = statusCode
8651cb0ef41Sopenharmony_ci    this.shouldKeepAlive = (
8661cb0ef41Sopenharmony_ci      shouldKeepAlive ||
8671cb0ef41Sopenharmony_ci      // Override llhttp value which does not allow keepAlive for HEAD.
8681cb0ef41Sopenharmony_ci      (request.method === 'HEAD' && !socket[kReset] && this.connection.toLowerCase() === 'keep-alive')
8691cb0ef41Sopenharmony_ci    )
8701cb0ef41Sopenharmony_ci
8711cb0ef41Sopenharmony_ci    if (this.statusCode >= 200) {
8721cb0ef41Sopenharmony_ci      const bodyTimeout = request.bodyTimeout != null
8731cb0ef41Sopenharmony_ci        ? request.bodyTimeout
8741cb0ef41Sopenharmony_ci        : client[kBodyTimeout]
8751cb0ef41Sopenharmony_ci      this.setTimeout(bodyTimeout, TIMEOUT_BODY)
8761cb0ef41Sopenharmony_ci    } else if (this.timeout) {
8771cb0ef41Sopenharmony_ci      // istanbul ignore else: only for jest
8781cb0ef41Sopenharmony_ci      if (this.timeout.refresh) {
8791cb0ef41Sopenharmony_ci        this.timeout.refresh()
8801cb0ef41Sopenharmony_ci      }
8811cb0ef41Sopenharmony_ci    }
8821cb0ef41Sopenharmony_ci
8831cb0ef41Sopenharmony_ci    if (request.method === 'CONNECT') {
8841cb0ef41Sopenharmony_ci      assert(client[kRunning] === 1)
8851cb0ef41Sopenharmony_ci      this.upgrade = true
8861cb0ef41Sopenharmony_ci      return 2
8871cb0ef41Sopenharmony_ci    }
8881cb0ef41Sopenharmony_ci
8891cb0ef41Sopenharmony_ci    if (upgrade) {
8901cb0ef41Sopenharmony_ci      assert(client[kRunning] === 1)
8911cb0ef41Sopenharmony_ci      this.upgrade = true
8921cb0ef41Sopenharmony_ci      return 2
8931cb0ef41Sopenharmony_ci    }
8941cb0ef41Sopenharmony_ci
8951cb0ef41Sopenharmony_ci    assert(this.headers.length % 2 === 0)
8961cb0ef41Sopenharmony_ci    this.headers = []
8971cb0ef41Sopenharmony_ci    this.headersSize = 0
8981cb0ef41Sopenharmony_ci
8991cb0ef41Sopenharmony_ci    if (this.shouldKeepAlive && client[kPipelining]) {
9001cb0ef41Sopenharmony_ci      const keepAliveTimeout = this.keepAlive ? util.parseKeepAliveTimeout(this.keepAlive) : null
9011cb0ef41Sopenharmony_ci
9021cb0ef41Sopenharmony_ci      if (keepAliveTimeout != null) {
9031cb0ef41Sopenharmony_ci        const timeout = Math.min(
9041cb0ef41Sopenharmony_ci          keepAliveTimeout - client[kKeepAliveTimeoutThreshold],
9051cb0ef41Sopenharmony_ci          client[kKeepAliveMaxTimeout]
9061cb0ef41Sopenharmony_ci        )
9071cb0ef41Sopenharmony_ci        if (timeout <= 0) {
9081cb0ef41Sopenharmony_ci          socket[kReset] = true
9091cb0ef41Sopenharmony_ci        } else {
9101cb0ef41Sopenharmony_ci          client[kKeepAliveTimeoutValue] = timeout
9111cb0ef41Sopenharmony_ci        }
9121cb0ef41Sopenharmony_ci      } else {
9131cb0ef41Sopenharmony_ci        client[kKeepAliveTimeoutValue] = client[kKeepAliveDefaultTimeout]
9141cb0ef41Sopenharmony_ci      }
9151cb0ef41Sopenharmony_ci    } else {
9161cb0ef41Sopenharmony_ci      // Stop more requests from being dispatched.
9171cb0ef41Sopenharmony_ci      socket[kReset] = true
9181cb0ef41Sopenharmony_ci    }
9191cb0ef41Sopenharmony_ci
9201cb0ef41Sopenharmony_ci    const pause = request.onHeaders(statusCode, headers, this.resume, statusText) === false
9211cb0ef41Sopenharmony_ci
9221cb0ef41Sopenharmony_ci    if (request.aborted) {
9231cb0ef41Sopenharmony_ci      return -1
9241cb0ef41Sopenharmony_ci    }
9251cb0ef41Sopenharmony_ci
9261cb0ef41Sopenharmony_ci    if (request.method === 'HEAD') {
9271cb0ef41Sopenharmony_ci      return 1
9281cb0ef41Sopenharmony_ci    }
9291cb0ef41Sopenharmony_ci
9301cb0ef41Sopenharmony_ci    if (statusCode < 200) {
9311cb0ef41Sopenharmony_ci      return 1
9321cb0ef41Sopenharmony_ci    }
9331cb0ef41Sopenharmony_ci
9341cb0ef41Sopenharmony_ci    if (socket[kBlocking]) {
9351cb0ef41Sopenharmony_ci      socket[kBlocking] = false
9361cb0ef41Sopenharmony_ci      resume(client)
9371cb0ef41Sopenharmony_ci    }
9381cb0ef41Sopenharmony_ci
9391cb0ef41Sopenharmony_ci    return pause ? constants.ERROR.PAUSED : 0
9401cb0ef41Sopenharmony_ci  }
9411cb0ef41Sopenharmony_ci
9421cb0ef41Sopenharmony_ci  onBody (buf) {
9431cb0ef41Sopenharmony_ci    const { client, socket, statusCode, maxResponseSize } = this
9441cb0ef41Sopenharmony_ci
9451cb0ef41Sopenharmony_ci    if (socket.destroyed) {
9461cb0ef41Sopenharmony_ci      return -1
9471cb0ef41Sopenharmony_ci    }
9481cb0ef41Sopenharmony_ci
9491cb0ef41Sopenharmony_ci    const request = client[kQueue][client[kRunningIdx]]
9501cb0ef41Sopenharmony_ci    assert(request)
9511cb0ef41Sopenharmony_ci
9521cb0ef41Sopenharmony_ci    assert.strictEqual(this.timeoutType, TIMEOUT_BODY)
9531cb0ef41Sopenharmony_ci    if (this.timeout) {
9541cb0ef41Sopenharmony_ci      // istanbul ignore else: only for jest
9551cb0ef41Sopenharmony_ci      if (this.timeout.refresh) {
9561cb0ef41Sopenharmony_ci        this.timeout.refresh()
9571cb0ef41Sopenharmony_ci      }
9581cb0ef41Sopenharmony_ci    }
9591cb0ef41Sopenharmony_ci
9601cb0ef41Sopenharmony_ci    assert(statusCode >= 200)
9611cb0ef41Sopenharmony_ci
9621cb0ef41Sopenharmony_ci    if (maxResponseSize > -1 && this.bytesRead + buf.length > maxResponseSize) {
9631cb0ef41Sopenharmony_ci      util.destroy(socket, new ResponseExceededMaxSizeError())
9641cb0ef41Sopenharmony_ci      return -1
9651cb0ef41Sopenharmony_ci    }
9661cb0ef41Sopenharmony_ci
9671cb0ef41Sopenharmony_ci    this.bytesRead += buf.length
9681cb0ef41Sopenharmony_ci
9691cb0ef41Sopenharmony_ci    if (request.onData(buf) === false) {
9701cb0ef41Sopenharmony_ci      return constants.ERROR.PAUSED
9711cb0ef41Sopenharmony_ci    }
9721cb0ef41Sopenharmony_ci  }
9731cb0ef41Sopenharmony_ci
9741cb0ef41Sopenharmony_ci  onMessageComplete () {
9751cb0ef41Sopenharmony_ci    const { client, socket, statusCode, upgrade, headers, contentLength, bytesRead, shouldKeepAlive } = this
9761cb0ef41Sopenharmony_ci
9771cb0ef41Sopenharmony_ci    if (socket.destroyed && (!statusCode || shouldKeepAlive)) {
9781cb0ef41Sopenharmony_ci      return -1
9791cb0ef41Sopenharmony_ci    }
9801cb0ef41Sopenharmony_ci
9811cb0ef41Sopenharmony_ci    if (upgrade) {
9821cb0ef41Sopenharmony_ci      return
9831cb0ef41Sopenharmony_ci    }
9841cb0ef41Sopenharmony_ci
9851cb0ef41Sopenharmony_ci    const request = client[kQueue][client[kRunningIdx]]
9861cb0ef41Sopenharmony_ci    assert(request)
9871cb0ef41Sopenharmony_ci
9881cb0ef41Sopenharmony_ci    assert(statusCode >= 100)
9891cb0ef41Sopenharmony_ci
9901cb0ef41Sopenharmony_ci    this.statusCode = null
9911cb0ef41Sopenharmony_ci    this.statusText = ''
9921cb0ef41Sopenharmony_ci    this.bytesRead = 0
9931cb0ef41Sopenharmony_ci    this.contentLength = ''
9941cb0ef41Sopenharmony_ci    this.keepAlive = ''
9951cb0ef41Sopenharmony_ci    this.connection = ''
9961cb0ef41Sopenharmony_ci
9971cb0ef41Sopenharmony_ci    assert(this.headers.length % 2 === 0)
9981cb0ef41Sopenharmony_ci    this.headers = []
9991cb0ef41Sopenharmony_ci    this.headersSize = 0
10001cb0ef41Sopenharmony_ci
10011cb0ef41Sopenharmony_ci    if (statusCode < 200) {
10021cb0ef41Sopenharmony_ci      return
10031cb0ef41Sopenharmony_ci    }
10041cb0ef41Sopenharmony_ci
10051cb0ef41Sopenharmony_ci    /* istanbul ignore next: should be handled by llhttp? */
10061cb0ef41Sopenharmony_ci    if (request.method !== 'HEAD' && contentLength && bytesRead !== parseInt(contentLength, 10)) {
10071cb0ef41Sopenharmony_ci      util.destroy(socket, new ResponseContentLengthMismatchError())
10081cb0ef41Sopenharmony_ci      return -1
10091cb0ef41Sopenharmony_ci    }
10101cb0ef41Sopenharmony_ci
10111cb0ef41Sopenharmony_ci    request.onComplete(headers)
10121cb0ef41Sopenharmony_ci
10131cb0ef41Sopenharmony_ci    client[kQueue][client[kRunningIdx]++] = null
10141cb0ef41Sopenharmony_ci
10151cb0ef41Sopenharmony_ci    if (socket[kWriting]) {
10161cb0ef41Sopenharmony_ci      assert.strictEqual(client[kRunning], 0)
10171cb0ef41Sopenharmony_ci      // Response completed before request.
10181cb0ef41Sopenharmony_ci      util.destroy(socket, new InformationalError('reset'))
10191cb0ef41Sopenharmony_ci      return constants.ERROR.PAUSED
10201cb0ef41Sopenharmony_ci    } else if (!shouldKeepAlive) {
10211cb0ef41Sopenharmony_ci      util.destroy(socket, new InformationalError('reset'))
10221cb0ef41Sopenharmony_ci      return constants.ERROR.PAUSED
10231cb0ef41Sopenharmony_ci    } else if (socket[kReset] && client[kRunning] === 0) {
10241cb0ef41Sopenharmony_ci      // Destroy socket once all requests have completed.
10251cb0ef41Sopenharmony_ci      // The request at the tail of the pipeline is the one
10261cb0ef41Sopenharmony_ci      // that requested reset and no further requests should
10271cb0ef41Sopenharmony_ci      // have been queued since then.
10281cb0ef41Sopenharmony_ci      util.destroy(socket, new InformationalError('reset'))
10291cb0ef41Sopenharmony_ci      return constants.ERROR.PAUSED
10301cb0ef41Sopenharmony_ci    } else if (client[kPipelining] === 1) {
10311cb0ef41Sopenharmony_ci      // We must wait a full event loop cycle to reuse this socket to make sure
10321cb0ef41Sopenharmony_ci      // that non-spec compliant servers are not closing the connection even if they
10331cb0ef41Sopenharmony_ci      // said they won't.
10341cb0ef41Sopenharmony_ci      setImmediate(resume, client)
10351cb0ef41Sopenharmony_ci    } else {
10361cb0ef41Sopenharmony_ci      resume(client)
10371cb0ef41Sopenharmony_ci    }
10381cb0ef41Sopenharmony_ci  }
10391cb0ef41Sopenharmony_ci}
10401cb0ef41Sopenharmony_ci
10411cb0ef41Sopenharmony_cifunction onParserTimeout (parser) {
10421cb0ef41Sopenharmony_ci  const { socket, timeoutType, client } = parser
10431cb0ef41Sopenharmony_ci
10441cb0ef41Sopenharmony_ci  /* istanbul ignore else */
10451cb0ef41Sopenharmony_ci  if (timeoutType === TIMEOUT_HEADERS) {
10461cb0ef41Sopenharmony_ci    if (!socket[kWriting] || socket.writableNeedDrain || client[kRunning] > 1) {
10471cb0ef41Sopenharmony_ci      assert(!parser.paused, 'cannot be paused while waiting for headers')
10481cb0ef41Sopenharmony_ci      util.destroy(socket, new HeadersTimeoutError())
10491cb0ef41Sopenharmony_ci    }
10501cb0ef41Sopenharmony_ci  } else if (timeoutType === TIMEOUT_BODY) {
10511cb0ef41Sopenharmony_ci    if (!parser.paused) {
10521cb0ef41Sopenharmony_ci      util.destroy(socket, new BodyTimeoutError())
10531cb0ef41Sopenharmony_ci    }
10541cb0ef41Sopenharmony_ci  } else if (timeoutType === TIMEOUT_IDLE) {
10551cb0ef41Sopenharmony_ci    assert(client[kRunning] === 0 && client[kKeepAliveTimeoutValue])
10561cb0ef41Sopenharmony_ci    util.destroy(socket, new InformationalError('socket idle timeout'))
10571cb0ef41Sopenharmony_ci  }
10581cb0ef41Sopenharmony_ci}
10591cb0ef41Sopenharmony_ci
10601cb0ef41Sopenharmony_cifunction onSocketReadable () {
10611cb0ef41Sopenharmony_ci  const { [kParser]: parser } = this
10621cb0ef41Sopenharmony_ci  if (parser) {
10631cb0ef41Sopenharmony_ci    parser.readMore()
10641cb0ef41Sopenharmony_ci  }
10651cb0ef41Sopenharmony_ci}
10661cb0ef41Sopenharmony_ci
10671cb0ef41Sopenharmony_cifunction onSocketError (err) {
10681cb0ef41Sopenharmony_ci  const { [kClient]: client, [kParser]: parser } = this
10691cb0ef41Sopenharmony_ci
10701cb0ef41Sopenharmony_ci  assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID')
10711cb0ef41Sopenharmony_ci
10721cb0ef41Sopenharmony_ci  if (client[kHTTPConnVersion] !== 'h2') {
10731cb0ef41Sopenharmony_ci    // On Mac OS, we get an ECONNRESET even if there is a full body to be forwarded
10741cb0ef41Sopenharmony_ci    // to the user.
10751cb0ef41Sopenharmony_ci    if (err.code === 'ECONNRESET' && parser.statusCode && !parser.shouldKeepAlive) {
10761cb0ef41Sopenharmony_ci      // We treat all incoming data so for as a valid response.
10771cb0ef41Sopenharmony_ci      parser.onMessageComplete()
10781cb0ef41Sopenharmony_ci      return
10791cb0ef41Sopenharmony_ci    }
10801cb0ef41Sopenharmony_ci  }
10811cb0ef41Sopenharmony_ci
10821cb0ef41Sopenharmony_ci  this[kError] = err
10831cb0ef41Sopenharmony_ci
10841cb0ef41Sopenharmony_ci  onError(this[kClient], err)
10851cb0ef41Sopenharmony_ci}
10861cb0ef41Sopenharmony_ci
10871cb0ef41Sopenharmony_cifunction onError (client, err) {
10881cb0ef41Sopenharmony_ci  if (
10891cb0ef41Sopenharmony_ci    client[kRunning] === 0 &&
10901cb0ef41Sopenharmony_ci    err.code !== 'UND_ERR_INFO' &&
10911cb0ef41Sopenharmony_ci    err.code !== 'UND_ERR_SOCKET'
10921cb0ef41Sopenharmony_ci  ) {
10931cb0ef41Sopenharmony_ci    // Error is not caused by running request and not a recoverable
10941cb0ef41Sopenharmony_ci    // socket error.
10951cb0ef41Sopenharmony_ci
10961cb0ef41Sopenharmony_ci    assert(client[kPendingIdx] === client[kRunningIdx])
10971cb0ef41Sopenharmony_ci
10981cb0ef41Sopenharmony_ci    const requests = client[kQueue].splice(client[kRunningIdx])
10991cb0ef41Sopenharmony_ci    for (let i = 0; i < requests.length; i++) {
11001cb0ef41Sopenharmony_ci      const request = requests[i]
11011cb0ef41Sopenharmony_ci      errorRequest(client, request, err)
11021cb0ef41Sopenharmony_ci    }
11031cb0ef41Sopenharmony_ci    assert(client[kSize] === 0)
11041cb0ef41Sopenharmony_ci  }
11051cb0ef41Sopenharmony_ci}
11061cb0ef41Sopenharmony_ci
11071cb0ef41Sopenharmony_cifunction onSocketEnd () {
11081cb0ef41Sopenharmony_ci  const { [kParser]: parser, [kClient]: client } = this
11091cb0ef41Sopenharmony_ci
11101cb0ef41Sopenharmony_ci  if (client[kHTTPConnVersion] !== 'h2') {
11111cb0ef41Sopenharmony_ci    if (parser.statusCode && !parser.shouldKeepAlive) {
11121cb0ef41Sopenharmony_ci      // We treat all incoming data so far as a valid response.
11131cb0ef41Sopenharmony_ci      parser.onMessageComplete()
11141cb0ef41Sopenharmony_ci      return
11151cb0ef41Sopenharmony_ci    }
11161cb0ef41Sopenharmony_ci  }
11171cb0ef41Sopenharmony_ci
11181cb0ef41Sopenharmony_ci  util.destroy(this, new SocketError('other side closed', util.getSocketInfo(this)))
11191cb0ef41Sopenharmony_ci}
11201cb0ef41Sopenharmony_ci
11211cb0ef41Sopenharmony_cifunction onSocketClose () {
11221cb0ef41Sopenharmony_ci  const { [kClient]: client, [kParser]: parser } = this
11231cb0ef41Sopenharmony_ci
11241cb0ef41Sopenharmony_ci  if (client[kHTTPConnVersion] === 'h1' && parser) {
11251cb0ef41Sopenharmony_ci    if (!this[kError] && parser.statusCode && !parser.shouldKeepAlive) {
11261cb0ef41Sopenharmony_ci      // We treat all incoming data so far as a valid response.
11271cb0ef41Sopenharmony_ci      parser.onMessageComplete()
11281cb0ef41Sopenharmony_ci    }
11291cb0ef41Sopenharmony_ci
11301cb0ef41Sopenharmony_ci    this[kParser].destroy()
11311cb0ef41Sopenharmony_ci    this[kParser] = null
11321cb0ef41Sopenharmony_ci  }
11331cb0ef41Sopenharmony_ci
11341cb0ef41Sopenharmony_ci  const err = this[kError] || new SocketError('closed', util.getSocketInfo(this))
11351cb0ef41Sopenharmony_ci
11361cb0ef41Sopenharmony_ci  client[kSocket] = null
11371cb0ef41Sopenharmony_ci
11381cb0ef41Sopenharmony_ci  if (client.destroyed) {
11391cb0ef41Sopenharmony_ci    assert(client[kPending] === 0)
11401cb0ef41Sopenharmony_ci
11411cb0ef41Sopenharmony_ci    // Fail entire queue.
11421cb0ef41Sopenharmony_ci    const requests = client[kQueue].splice(client[kRunningIdx])
11431cb0ef41Sopenharmony_ci    for (let i = 0; i < requests.length; i++) {
11441cb0ef41Sopenharmony_ci      const request = requests[i]
11451cb0ef41Sopenharmony_ci      errorRequest(client, request, err)
11461cb0ef41Sopenharmony_ci    }
11471cb0ef41Sopenharmony_ci  } else if (client[kRunning] > 0 && err.code !== 'UND_ERR_INFO') {
11481cb0ef41Sopenharmony_ci    // Fail head of pipeline.
11491cb0ef41Sopenharmony_ci    const request = client[kQueue][client[kRunningIdx]]
11501cb0ef41Sopenharmony_ci    client[kQueue][client[kRunningIdx]++] = null
11511cb0ef41Sopenharmony_ci
11521cb0ef41Sopenharmony_ci    errorRequest(client, request, err)
11531cb0ef41Sopenharmony_ci  }
11541cb0ef41Sopenharmony_ci
11551cb0ef41Sopenharmony_ci  client[kPendingIdx] = client[kRunningIdx]
11561cb0ef41Sopenharmony_ci
11571cb0ef41Sopenharmony_ci  assert(client[kRunning] === 0)
11581cb0ef41Sopenharmony_ci
11591cb0ef41Sopenharmony_ci  client.emit('disconnect', client[kUrl], [client], err)
11601cb0ef41Sopenharmony_ci
11611cb0ef41Sopenharmony_ci  resume(client)
11621cb0ef41Sopenharmony_ci}
11631cb0ef41Sopenharmony_ci
11641cb0ef41Sopenharmony_ciasync function connect (client) {
11651cb0ef41Sopenharmony_ci  assert(!client[kConnecting])
11661cb0ef41Sopenharmony_ci  assert(!client[kSocket])
11671cb0ef41Sopenharmony_ci
11681cb0ef41Sopenharmony_ci  let { host, hostname, protocol, port } = client[kUrl]
11691cb0ef41Sopenharmony_ci
11701cb0ef41Sopenharmony_ci  // Resolve ipv6
11711cb0ef41Sopenharmony_ci  if (hostname[0] === '[') {
11721cb0ef41Sopenharmony_ci    const idx = hostname.indexOf(']')
11731cb0ef41Sopenharmony_ci
11741cb0ef41Sopenharmony_ci    assert(idx !== -1)
11751cb0ef41Sopenharmony_ci    const ip = hostname.substring(1, idx)
11761cb0ef41Sopenharmony_ci
11771cb0ef41Sopenharmony_ci    assert(net.isIP(ip))
11781cb0ef41Sopenharmony_ci    hostname = ip
11791cb0ef41Sopenharmony_ci  }
11801cb0ef41Sopenharmony_ci
11811cb0ef41Sopenharmony_ci  client[kConnecting] = true
11821cb0ef41Sopenharmony_ci
11831cb0ef41Sopenharmony_ci  if (channels.beforeConnect.hasSubscribers) {
11841cb0ef41Sopenharmony_ci    channels.beforeConnect.publish({
11851cb0ef41Sopenharmony_ci      connectParams: {
11861cb0ef41Sopenharmony_ci        host,
11871cb0ef41Sopenharmony_ci        hostname,
11881cb0ef41Sopenharmony_ci        protocol,
11891cb0ef41Sopenharmony_ci        port,
11901cb0ef41Sopenharmony_ci        servername: client[kServerName],
11911cb0ef41Sopenharmony_ci        localAddress: client[kLocalAddress]
11921cb0ef41Sopenharmony_ci      },
11931cb0ef41Sopenharmony_ci      connector: client[kConnector]
11941cb0ef41Sopenharmony_ci    })
11951cb0ef41Sopenharmony_ci  }
11961cb0ef41Sopenharmony_ci
11971cb0ef41Sopenharmony_ci  try {
11981cb0ef41Sopenharmony_ci    const socket = await new Promise((resolve, reject) => {
11991cb0ef41Sopenharmony_ci      client[kConnector]({
12001cb0ef41Sopenharmony_ci        host,
12011cb0ef41Sopenharmony_ci        hostname,
12021cb0ef41Sopenharmony_ci        protocol,
12031cb0ef41Sopenharmony_ci        port,
12041cb0ef41Sopenharmony_ci        servername: client[kServerName],
12051cb0ef41Sopenharmony_ci        localAddress: client[kLocalAddress]
12061cb0ef41Sopenharmony_ci      }, (err, socket) => {
12071cb0ef41Sopenharmony_ci        if (err) {
12081cb0ef41Sopenharmony_ci          reject(err)
12091cb0ef41Sopenharmony_ci        } else {
12101cb0ef41Sopenharmony_ci          resolve(socket)
12111cb0ef41Sopenharmony_ci        }
12121cb0ef41Sopenharmony_ci      })
12131cb0ef41Sopenharmony_ci    })
12141cb0ef41Sopenharmony_ci
12151cb0ef41Sopenharmony_ci    if (client.destroyed) {
12161cb0ef41Sopenharmony_ci      util.destroy(socket.on('error', () => {}), new ClientDestroyedError())
12171cb0ef41Sopenharmony_ci      return
12181cb0ef41Sopenharmony_ci    }
12191cb0ef41Sopenharmony_ci
12201cb0ef41Sopenharmony_ci    client[kConnecting] = false
12211cb0ef41Sopenharmony_ci
12221cb0ef41Sopenharmony_ci    assert(socket)
12231cb0ef41Sopenharmony_ci
12241cb0ef41Sopenharmony_ci    const isH2 = socket.alpnProtocol === 'h2'
12251cb0ef41Sopenharmony_ci    if (isH2) {
12261cb0ef41Sopenharmony_ci      if (!h2ExperimentalWarned) {
12271cb0ef41Sopenharmony_ci        h2ExperimentalWarned = true
12281cb0ef41Sopenharmony_ci        process.emitWarning('H2 support is experimental, expect them to change at any time.', {
12291cb0ef41Sopenharmony_ci          code: 'UNDICI-H2'
12301cb0ef41Sopenharmony_ci        })
12311cb0ef41Sopenharmony_ci      }
12321cb0ef41Sopenharmony_ci
12331cb0ef41Sopenharmony_ci      const session = http2.connect(client[kUrl], {
12341cb0ef41Sopenharmony_ci        createConnection: () => socket,
12351cb0ef41Sopenharmony_ci        peerMaxConcurrentStreams: client[kHTTP2SessionState].maxConcurrentStreams
12361cb0ef41Sopenharmony_ci      })
12371cb0ef41Sopenharmony_ci
12381cb0ef41Sopenharmony_ci      client[kHTTPConnVersion] = 'h2'
12391cb0ef41Sopenharmony_ci      session[kClient] = client
12401cb0ef41Sopenharmony_ci      session[kSocket] = socket
12411cb0ef41Sopenharmony_ci      session.on('error', onHttp2SessionError)
12421cb0ef41Sopenharmony_ci      session.on('frameError', onHttp2FrameError)
12431cb0ef41Sopenharmony_ci      session.on('end', onHttp2SessionEnd)
12441cb0ef41Sopenharmony_ci      session.on('goaway', onHTTP2GoAway)
12451cb0ef41Sopenharmony_ci      session.on('close', onSocketClose)
12461cb0ef41Sopenharmony_ci      session.unref()
12471cb0ef41Sopenharmony_ci
12481cb0ef41Sopenharmony_ci      client[kHTTP2Session] = session
12491cb0ef41Sopenharmony_ci      socket[kHTTP2Session] = session
12501cb0ef41Sopenharmony_ci    } else {
12511cb0ef41Sopenharmony_ci      if (!llhttpInstance) {
12521cb0ef41Sopenharmony_ci        llhttpInstance = await llhttpPromise
12531cb0ef41Sopenharmony_ci        llhttpPromise = null
12541cb0ef41Sopenharmony_ci      }
12551cb0ef41Sopenharmony_ci
12561cb0ef41Sopenharmony_ci      socket[kNoRef] = false
12571cb0ef41Sopenharmony_ci      socket[kWriting] = false
12581cb0ef41Sopenharmony_ci      socket[kReset] = false
12591cb0ef41Sopenharmony_ci      socket[kBlocking] = false
12601cb0ef41Sopenharmony_ci      socket[kParser] = new Parser(client, socket, llhttpInstance)
12611cb0ef41Sopenharmony_ci    }
12621cb0ef41Sopenharmony_ci
12631cb0ef41Sopenharmony_ci    socket[kCounter] = 0
12641cb0ef41Sopenharmony_ci    socket[kMaxRequests] = client[kMaxRequests]
12651cb0ef41Sopenharmony_ci    socket[kClient] = client
12661cb0ef41Sopenharmony_ci    socket[kError] = null
12671cb0ef41Sopenharmony_ci
12681cb0ef41Sopenharmony_ci    socket
12691cb0ef41Sopenharmony_ci      .on('error', onSocketError)
12701cb0ef41Sopenharmony_ci      .on('readable', onSocketReadable)
12711cb0ef41Sopenharmony_ci      .on('end', onSocketEnd)
12721cb0ef41Sopenharmony_ci      .on('close', onSocketClose)
12731cb0ef41Sopenharmony_ci
12741cb0ef41Sopenharmony_ci    client[kSocket] = socket
12751cb0ef41Sopenharmony_ci
12761cb0ef41Sopenharmony_ci    if (channels.connected.hasSubscribers) {
12771cb0ef41Sopenharmony_ci      channels.connected.publish({
12781cb0ef41Sopenharmony_ci        connectParams: {
12791cb0ef41Sopenharmony_ci          host,
12801cb0ef41Sopenharmony_ci          hostname,
12811cb0ef41Sopenharmony_ci          protocol,
12821cb0ef41Sopenharmony_ci          port,
12831cb0ef41Sopenharmony_ci          servername: client[kServerName],
12841cb0ef41Sopenharmony_ci          localAddress: client[kLocalAddress]
12851cb0ef41Sopenharmony_ci        },
12861cb0ef41Sopenharmony_ci        connector: client[kConnector],
12871cb0ef41Sopenharmony_ci        socket
12881cb0ef41Sopenharmony_ci      })
12891cb0ef41Sopenharmony_ci    }
12901cb0ef41Sopenharmony_ci    client.emit('connect', client[kUrl], [client])
12911cb0ef41Sopenharmony_ci  } catch (err) {
12921cb0ef41Sopenharmony_ci    if (client.destroyed) {
12931cb0ef41Sopenharmony_ci      return
12941cb0ef41Sopenharmony_ci    }
12951cb0ef41Sopenharmony_ci
12961cb0ef41Sopenharmony_ci    client[kConnecting] = false
12971cb0ef41Sopenharmony_ci
12981cb0ef41Sopenharmony_ci    if (channels.connectError.hasSubscribers) {
12991cb0ef41Sopenharmony_ci      channels.connectError.publish({
13001cb0ef41Sopenharmony_ci        connectParams: {
13011cb0ef41Sopenharmony_ci          host,
13021cb0ef41Sopenharmony_ci          hostname,
13031cb0ef41Sopenharmony_ci          protocol,
13041cb0ef41Sopenharmony_ci          port,
13051cb0ef41Sopenharmony_ci          servername: client[kServerName],
13061cb0ef41Sopenharmony_ci          localAddress: client[kLocalAddress]
13071cb0ef41Sopenharmony_ci        },
13081cb0ef41Sopenharmony_ci        connector: client[kConnector],
13091cb0ef41Sopenharmony_ci        error: err
13101cb0ef41Sopenharmony_ci      })
13111cb0ef41Sopenharmony_ci    }
13121cb0ef41Sopenharmony_ci
13131cb0ef41Sopenharmony_ci    if (err.code === 'ERR_TLS_CERT_ALTNAME_INVALID') {
13141cb0ef41Sopenharmony_ci      assert(client[kRunning] === 0)
13151cb0ef41Sopenharmony_ci      while (client[kPending] > 0 && client[kQueue][client[kPendingIdx]].servername === client[kServerName]) {
13161cb0ef41Sopenharmony_ci        const request = client[kQueue][client[kPendingIdx]++]
13171cb0ef41Sopenharmony_ci        errorRequest(client, request, err)
13181cb0ef41Sopenharmony_ci      }
13191cb0ef41Sopenharmony_ci    } else {
13201cb0ef41Sopenharmony_ci      onError(client, err)
13211cb0ef41Sopenharmony_ci    }
13221cb0ef41Sopenharmony_ci
13231cb0ef41Sopenharmony_ci    client.emit('connectionError', client[kUrl], [client], err)
13241cb0ef41Sopenharmony_ci  }
13251cb0ef41Sopenharmony_ci
13261cb0ef41Sopenharmony_ci  resume(client)
13271cb0ef41Sopenharmony_ci}
13281cb0ef41Sopenharmony_ci
13291cb0ef41Sopenharmony_cifunction emitDrain (client) {
13301cb0ef41Sopenharmony_ci  client[kNeedDrain] = 0
13311cb0ef41Sopenharmony_ci  client.emit('drain', client[kUrl], [client])
13321cb0ef41Sopenharmony_ci}
13331cb0ef41Sopenharmony_ci
13341cb0ef41Sopenharmony_cifunction resume (client, sync) {
13351cb0ef41Sopenharmony_ci  if (client[kResuming] === 2) {
13361cb0ef41Sopenharmony_ci    return
13371cb0ef41Sopenharmony_ci  }
13381cb0ef41Sopenharmony_ci
13391cb0ef41Sopenharmony_ci  client[kResuming] = 2
13401cb0ef41Sopenharmony_ci
13411cb0ef41Sopenharmony_ci  _resume(client, sync)
13421cb0ef41Sopenharmony_ci  client[kResuming] = 0
13431cb0ef41Sopenharmony_ci
13441cb0ef41Sopenharmony_ci  if (client[kRunningIdx] > 256) {
13451cb0ef41Sopenharmony_ci    client[kQueue].splice(0, client[kRunningIdx])
13461cb0ef41Sopenharmony_ci    client[kPendingIdx] -= client[kRunningIdx]
13471cb0ef41Sopenharmony_ci    client[kRunningIdx] = 0
13481cb0ef41Sopenharmony_ci  }
13491cb0ef41Sopenharmony_ci}
13501cb0ef41Sopenharmony_ci
13511cb0ef41Sopenharmony_cifunction _resume (client, sync) {
13521cb0ef41Sopenharmony_ci  while (true) {
13531cb0ef41Sopenharmony_ci    if (client.destroyed) {
13541cb0ef41Sopenharmony_ci      assert(client[kPending] === 0)
13551cb0ef41Sopenharmony_ci      return
13561cb0ef41Sopenharmony_ci    }
13571cb0ef41Sopenharmony_ci
13581cb0ef41Sopenharmony_ci    if (client[kClosedResolve] && !client[kSize]) {
13591cb0ef41Sopenharmony_ci      client[kClosedResolve]()
13601cb0ef41Sopenharmony_ci      client[kClosedResolve] = null
13611cb0ef41Sopenharmony_ci      return
13621cb0ef41Sopenharmony_ci    }
13631cb0ef41Sopenharmony_ci
13641cb0ef41Sopenharmony_ci    const socket = client[kSocket]
13651cb0ef41Sopenharmony_ci
13661cb0ef41Sopenharmony_ci    if (socket && !socket.destroyed && socket.alpnProtocol !== 'h2') {
13671cb0ef41Sopenharmony_ci      if (client[kSize] === 0) {
13681cb0ef41Sopenharmony_ci        if (!socket[kNoRef] && socket.unref) {
13691cb0ef41Sopenharmony_ci          socket.unref()
13701cb0ef41Sopenharmony_ci          socket[kNoRef] = true
13711cb0ef41Sopenharmony_ci        }
13721cb0ef41Sopenharmony_ci      } else if (socket[kNoRef] && socket.ref) {
13731cb0ef41Sopenharmony_ci        socket.ref()
13741cb0ef41Sopenharmony_ci        socket[kNoRef] = false
13751cb0ef41Sopenharmony_ci      }
13761cb0ef41Sopenharmony_ci
13771cb0ef41Sopenharmony_ci      if (client[kSize] === 0) {
13781cb0ef41Sopenharmony_ci        if (socket[kParser].timeoutType !== TIMEOUT_IDLE) {
13791cb0ef41Sopenharmony_ci          socket[kParser].setTimeout(client[kKeepAliveTimeoutValue], TIMEOUT_IDLE)
13801cb0ef41Sopenharmony_ci        }
13811cb0ef41Sopenharmony_ci      } else if (client[kRunning] > 0 && socket[kParser].statusCode < 200) {
13821cb0ef41Sopenharmony_ci        if (socket[kParser].timeoutType !== TIMEOUT_HEADERS) {
13831cb0ef41Sopenharmony_ci          const request = client[kQueue][client[kRunningIdx]]
13841cb0ef41Sopenharmony_ci          const headersTimeout = request.headersTimeout != null
13851cb0ef41Sopenharmony_ci            ? request.headersTimeout
13861cb0ef41Sopenharmony_ci            : client[kHeadersTimeout]
13871cb0ef41Sopenharmony_ci          socket[kParser].setTimeout(headersTimeout, TIMEOUT_HEADERS)
13881cb0ef41Sopenharmony_ci        }
13891cb0ef41Sopenharmony_ci      }
13901cb0ef41Sopenharmony_ci    }
13911cb0ef41Sopenharmony_ci
13921cb0ef41Sopenharmony_ci    if (client[kBusy]) {
13931cb0ef41Sopenharmony_ci      client[kNeedDrain] = 2
13941cb0ef41Sopenharmony_ci    } else if (client[kNeedDrain] === 2) {
13951cb0ef41Sopenharmony_ci      if (sync) {
13961cb0ef41Sopenharmony_ci        client[kNeedDrain] = 1
13971cb0ef41Sopenharmony_ci        process.nextTick(emitDrain, client)
13981cb0ef41Sopenharmony_ci      } else {
13991cb0ef41Sopenharmony_ci        emitDrain(client)
14001cb0ef41Sopenharmony_ci      }
14011cb0ef41Sopenharmony_ci      continue
14021cb0ef41Sopenharmony_ci    }
14031cb0ef41Sopenharmony_ci
14041cb0ef41Sopenharmony_ci    if (client[kPending] === 0) {
14051cb0ef41Sopenharmony_ci      return
14061cb0ef41Sopenharmony_ci    }
14071cb0ef41Sopenharmony_ci
14081cb0ef41Sopenharmony_ci    if (client[kRunning] >= (client[kPipelining] || 1)) {
14091cb0ef41Sopenharmony_ci      return
14101cb0ef41Sopenharmony_ci    }
14111cb0ef41Sopenharmony_ci
14121cb0ef41Sopenharmony_ci    const request = client[kQueue][client[kPendingIdx]]
14131cb0ef41Sopenharmony_ci
14141cb0ef41Sopenharmony_ci    if (client[kUrl].protocol === 'https:' && client[kServerName] !== request.servername) {
14151cb0ef41Sopenharmony_ci      if (client[kRunning] > 0) {
14161cb0ef41Sopenharmony_ci        return
14171cb0ef41Sopenharmony_ci      }
14181cb0ef41Sopenharmony_ci
14191cb0ef41Sopenharmony_ci      client[kServerName] = request.servername
14201cb0ef41Sopenharmony_ci
14211cb0ef41Sopenharmony_ci      if (socket && socket.servername !== request.servername) {
14221cb0ef41Sopenharmony_ci        util.destroy(socket, new InformationalError('servername changed'))
14231cb0ef41Sopenharmony_ci        return
14241cb0ef41Sopenharmony_ci      }
14251cb0ef41Sopenharmony_ci    }
14261cb0ef41Sopenharmony_ci
14271cb0ef41Sopenharmony_ci    if (client[kConnecting]) {
14281cb0ef41Sopenharmony_ci      return
14291cb0ef41Sopenharmony_ci    }
14301cb0ef41Sopenharmony_ci
14311cb0ef41Sopenharmony_ci    if (!socket && !client[kHTTP2Session]) {
14321cb0ef41Sopenharmony_ci      connect(client)
14331cb0ef41Sopenharmony_ci      return
14341cb0ef41Sopenharmony_ci    }
14351cb0ef41Sopenharmony_ci
14361cb0ef41Sopenharmony_ci    if (socket.destroyed || socket[kWriting] || socket[kReset] || socket[kBlocking]) {
14371cb0ef41Sopenharmony_ci      return
14381cb0ef41Sopenharmony_ci    }
14391cb0ef41Sopenharmony_ci
14401cb0ef41Sopenharmony_ci    if (client[kRunning] > 0 && !request.idempotent) {
14411cb0ef41Sopenharmony_ci      // Non-idempotent request cannot be retried.
14421cb0ef41Sopenharmony_ci      // Ensure that no other requests are inflight and
14431cb0ef41Sopenharmony_ci      // could cause failure.
14441cb0ef41Sopenharmony_ci      return
14451cb0ef41Sopenharmony_ci    }
14461cb0ef41Sopenharmony_ci
14471cb0ef41Sopenharmony_ci    if (client[kRunning] > 0 && (request.upgrade || request.method === 'CONNECT')) {
14481cb0ef41Sopenharmony_ci      // Don't dispatch an upgrade until all preceding requests have completed.
14491cb0ef41Sopenharmony_ci      // A misbehaving server might upgrade the connection before all pipelined
14501cb0ef41Sopenharmony_ci      // request has completed.
14511cb0ef41Sopenharmony_ci      return
14521cb0ef41Sopenharmony_ci    }
14531cb0ef41Sopenharmony_ci
14541cb0ef41Sopenharmony_ci    if (client[kRunning] > 0 && util.bodyLength(request.body) !== 0 &&
14551cb0ef41Sopenharmony_ci      (util.isStream(request.body) || util.isAsyncIterable(request.body))) {
14561cb0ef41Sopenharmony_ci      // Request with stream or iterator body can error while other requests
14571cb0ef41Sopenharmony_ci      // are inflight and indirectly error those as well.
14581cb0ef41Sopenharmony_ci      // Ensure this doesn't happen by waiting for inflight
14591cb0ef41Sopenharmony_ci      // to complete before dispatching.
14601cb0ef41Sopenharmony_ci
14611cb0ef41Sopenharmony_ci      // Request with stream or iterator body cannot be retried.
14621cb0ef41Sopenharmony_ci      // Ensure that no other requests are inflight and
14631cb0ef41Sopenharmony_ci      // could cause failure.
14641cb0ef41Sopenharmony_ci      return
14651cb0ef41Sopenharmony_ci    }
14661cb0ef41Sopenharmony_ci
14671cb0ef41Sopenharmony_ci    if (!request.aborted && write(client, request)) {
14681cb0ef41Sopenharmony_ci      client[kPendingIdx]++
14691cb0ef41Sopenharmony_ci    } else {
14701cb0ef41Sopenharmony_ci      client[kQueue].splice(client[kPendingIdx], 1)
14711cb0ef41Sopenharmony_ci    }
14721cb0ef41Sopenharmony_ci  }
14731cb0ef41Sopenharmony_ci}
14741cb0ef41Sopenharmony_ci
14751cb0ef41Sopenharmony_ci// https://www.rfc-editor.org/rfc/rfc7230#section-3.3.2
14761cb0ef41Sopenharmony_cifunction shouldSendContentLength (method) {
14771cb0ef41Sopenharmony_ci  return method !== 'GET' && method !== 'HEAD' && method !== 'OPTIONS' && method !== 'TRACE' && method !== 'CONNECT'
14781cb0ef41Sopenharmony_ci}
14791cb0ef41Sopenharmony_ci
14801cb0ef41Sopenharmony_cifunction write (client, request) {
14811cb0ef41Sopenharmony_ci  if (client[kHTTPConnVersion] === 'h2') {
14821cb0ef41Sopenharmony_ci    writeH2(client, client[kHTTP2Session], request)
14831cb0ef41Sopenharmony_ci    return
14841cb0ef41Sopenharmony_ci  }
14851cb0ef41Sopenharmony_ci
14861cb0ef41Sopenharmony_ci  const { body, method, path, host, upgrade, headers, blocking, reset } = request
14871cb0ef41Sopenharmony_ci
14881cb0ef41Sopenharmony_ci  // https://tools.ietf.org/html/rfc7231#section-4.3.1
14891cb0ef41Sopenharmony_ci  // https://tools.ietf.org/html/rfc7231#section-4.3.2
14901cb0ef41Sopenharmony_ci  // https://tools.ietf.org/html/rfc7231#section-4.3.5
14911cb0ef41Sopenharmony_ci
14921cb0ef41Sopenharmony_ci  // Sending a payload body on a request that does not
14931cb0ef41Sopenharmony_ci  // expect it can cause undefined behavior on some
14941cb0ef41Sopenharmony_ci  // servers and corrupt connection state. Do not
14951cb0ef41Sopenharmony_ci  // re-use the connection for further requests.
14961cb0ef41Sopenharmony_ci
14971cb0ef41Sopenharmony_ci  const expectsPayload = (
14981cb0ef41Sopenharmony_ci    method === 'PUT' ||
14991cb0ef41Sopenharmony_ci    method === 'POST' ||
15001cb0ef41Sopenharmony_ci    method === 'PATCH'
15011cb0ef41Sopenharmony_ci  )
15021cb0ef41Sopenharmony_ci
15031cb0ef41Sopenharmony_ci  if (body && typeof body.read === 'function') {
15041cb0ef41Sopenharmony_ci    // Try to read EOF in order to get length.
15051cb0ef41Sopenharmony_ci    body.read(0)
15061cb0ef41Sopenharmony_ci  }
15071cb0ef41Sopenharmony_ci
15081cb0ef41Sopenharmony_ci  const bodyLength = util.bodyLength(body)
15091cb0ef41Sopenharmony_ci
15101cb0ef41Sopenharmony_ci  let contentLength = bodyLength
15111cb0ef41Sopenharmony_ci
15121cb0ef41Sopenharmony_ci  if (contentLength === null) {
15131cb0ef41Sopenharmony_ci    contentLength = request.contentLength
15141cb0ef41Sopenharmony_ci  }
15151cb0ef41Sopenharmony_ci
15161cb0ef41Sopenharmony_ci  if (contentLength === 0 && !expectsPayload) {
15171cb0ef41Sopenharmony_ci    // https://tools.ietf.org/html/rfc7230#section-3.3.2
15181cb0ef41Sopenharmony_ci    // A user agent SHOULD NOT send a Content-Length header field when
15191cb0ef41Sopenharmony_ci    // the request message does not contain a payload body and the method
15201cb0ef41Sopenharmony_ci    // semantics do not anticipate such a body.
15211cb0ef41Sopenharmony_ci
15221cb0ef41Sopenharmony_ci    contentLength = null
15231cb0ef41Sopenharmony_ci  }
15241cb0ef41Sopenharmony_ci
15251cb0ef41Sopenharmony_ci  // https://github.com/nodejs/undici/issues/2046
15261cb0ef41Sopenharmony_ci  // A user agent may send a Content-Length header with 0 value, this should be allowed.
15271cb0ef41Sopenharmony_ci  if (shouldSendContentLength(method) && contentLength > 0 && request.contentLength !== null && request.contentLength !== contentLength) {
15281cb0ef41Sopenharmony_ci    if (client[kStrictContentLength]) {
15291cb0ef41Sopenharmony_ci      errorRequest(client, request, new RequestContentLengthMismatchError())
15301cb0ef41Sopenharmony_ci      return false
15311cb0ef41Sopenharmony_ci    }
15321cb0ef41Sopenharmony_ci
15331cb0ef41Sopenharmony_ci    process.emitWarning(new RequestContentLengthMismatchError())
15341cb0ef41Sopenharmony_ci  }
15351cb0ef41Sopenharmony_ci
15361cb0ef41Sopenharmony_ci  const socket = client[kSocket]
15371cb0ef41Sopenharmony_ci
15381cb0ef41Sopenharmony_ci  try {
15391cb0ef41Sopenharmony_ci    request.onConnect((err) => {
15401cb0ef41Sopenharmony_ci      if (request.aborted || request.completed) {
15411cb0ef41Sopenharmony_ci        return
15421cb0ef41Sopenharmony_ci      }
15431cb0ef41Sopenharmony_ci
15441cb0ef41Sopenharmony_ci      errorRequest(client, request, err || new RequestAbortedError())
15451cb0ef41Sopenharmony_ci
15461cb0ef41Sopenharmony_ci      util.destroy(socket, new InformationalError('aborted'))
15471cb0ef41Sopenharmony_ci    })
15481cb0ef41Sopenharmony_ci  } catch (err) {
15491cb0ef41Sopenharmony_ci    errorRequest(client, request, err)
15501cb0ef41Sopenharmony_ci  }
15511cb0ef41Sopenharmony_ci
15521cb0ef41Sopenharmony_ci  if (request.aborted) {
15531cb0ef41Sopenharmony_ci    return false
15541cb0ef41Sopenharmony_ci  }
15551cb0ef41Sopenharmony_ci
15561cb0ef41Sopenharmony_ci  if (method === 'HEAD') {
15571cb0ef41Sopenharmony_ci    // https://github.com/mcollina/undici/issues/258
15581cb0ef41Sopenharmony_ci    // Close after a HEAD request to interop with misbehaving servers
15591cb0ef41Sopenharmony_ci    // that may send a body in the response.
15601cb0ef41Sopenharmony_ci
15611cb0ef41Sopenharmony_ci    socket[kReset] = true
15621cb0ef41Sopenharmony_ci  }
15631cb0ef41Sopenharmony_ci
15641cb0ef41Sopenharmony_ci  if (upgrade || method === 'CONNECT') {
15651cb0ef41Sopenharmony_ci    // On CONNECT or upgrade, block pipeline from dispatching further
15661cb0ef41Sopenharmony_ci    // requests on this connection.
15671cb0ef41Sopenharmony_ci
15681cb0ef41Sopenharmony_ci    socket[kReset] = true
15691cb0ef41Sopenharmony_ci  }
15701cb0ef41Sopenharmony_ci
15711cb0ef41Sopenharmony_ci  if (reset != null) {
15721cb0ef41Sopenharmony_ci    socket[kReset] = reset
15731cb0ef41Sopenharmony_ci  }
15741cb0ef41Sopenharmony_ci
15751cb0ef41Sopenharmony_ci  if (client[kMaxRequests] && socket[kCounter]++ >= client[kMaxRequests]) {
15761cb0ef41Sopenharmony_ci    socket[kReset] = true
15771cb0ef41Sopenharmony_ci  }
15781cb0ef41Sopenharmony_ci
15791cb0ef41Sopenharmony_ci  if (blocking) {
15801cb0ef41Sopenharmony_ci    socket[kBlocking] = true
15811cb0ef41Sopenharmony_ci  }
15821cb0ef41Sopenharmony_ci
15831cb0ef41Sopenharmony_ci  let header = `${method} ${path} HTTP/1.1\r\n`
15841cb0ef41Sopenharmony_ci
15851cb0ef41Sopenharmony_ci  if (typeof host === 'string') {
15861cb0ef41Sopenharmony_ci    header += `host: ${host}\r\n`
15871cb0ef41Sopenharmony_ci  } else {
15881cb0ef41Sopenharmony_ci    header += client[kHostHeader]
15891cb0ef41Sopenharmony_ci  }
15901cb0ef41Sopenharmony_ci
15911cb0ef41Sopenharmony_ci  if (upgrade) {
15921cb0ef41Sopenharmony_ci    header += `connection: upgrade\r\nupgrade: ${upgrade}\r\n`
15931cb0ef41Sopenharmony_ci  } else if (client[kPipelining] && !socket[kReset]) {
15941cb0ef41Sopenharmony_ci    header += 'connection: keep-alive\r\n'
15951cb0ef41Sopenharmony_ci  } else {
15961cb0ef41Sopenharmony_ci    header += 'connection: close\r\n'
15971cb0ef41Sopenharmony_ci  }
15981cb0ef41Sopenharmony_ci
15991cb0ef41Sopenharmony_ci  if (headers) {
16001cb0ef41Sopenharmony_ci    header += headers
16011cb0ef41Sopenharmony_ci  }
16021cb0ef41Sopenharmony_ci
16031cb0ef41Sopenharmony_ci  if (channels.sendHeaders.hasSubscribers) {
16041cb0ef41Sopenharmony_ci    channels.sendHeaders.publish({ request, headers: header, socket })
16051cb0ef41Sopenharmony_ci  }
16061cb0ef41Sopenharmony_ci
16071cb0ef41Sopenharmony_ci  /* istanbul ignore else: assertion */
16081cb0ef41Sopenharmony_ci  if (!body || bodyLength === 0) {
16091cb0ef41Sopenharmony_ci    if (contentLength === 0) {
16101cb0ef41Sopenharmony_ci      socket.write(`${header}content-length: 0\r\n\r\n`, 'latin1')
16111cb0ef41Sopenharmony_ci    } else {
16121cb0ef41Sopenharmony_ci      assert(contentLength === null, 'no body must not have content length')
16131cb0ef41Sopenharmony_ci      socket.write(`${header}\r\n`, 'latin1')
16141cb0ef41Sopenharmony_ci    }
16151cb0ef41Sopenharmony_ci    request.onRequestSent()
16161cb0ef41Sopenharmony_ci  } else if (util.isBuffer(body)) {
16171cb0ef41Sopenharmony_ci    assert(contentLength === body.byteLength, 'buffer body must have content length')
16181cb0ef41Sopenharmony_ci
16191cb0ef41Sopenharmony_ci    socket.cork()
16201cb0ef41Sopenharmony_ci    socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'latin1')
16211cb0ef41Sopenharmony_ci    socket.write(body)
16221cb0ef41Sopenharmony_ci    socket.uncork()
16231cb0ef41Sopenharmony_ci    request.onBodySent(body)
16241cb0ef41Sopenharmony_ci    request.onRequestSent()
16251cb0ef41Sopenharmony_ci    if (!expectsPayload) {
16261cb0ef41Sopenharmony_ci      socket[kReset] = true
16271cb0ef41Sopenharmony_ci    }
16281cb0ef41Sopenharmony_ci  } else if (util.isBlobLike(body)) {
16291cb0ef41Sopenharmony_ci    if (typeof body.stream === 'function') {
16301cb0ef41Sopenharmony_ci      writeIterable({ body: body.stream(), client, request, socket, contentLength, header, expectsPayload })
16311cb0ef41Sopenharmony_ci    } else {
16321cb0ef41Sopenharmony_ci      writeBlob({ body, client, request, socket, contentLength, header, expectsPayload })
16331cb0ef41Sopenharmony_ci    }
16341cb0ef41Sopenharmony_ci  } else if (util.isStream(body)) {
16351cb0ef41Sopenharmony_ci    writeStream({ body, client, request, socket, contentLength, header, expectsPayload })
16361cb0ef41Sopenharmony_ci  } else if (util.isIterable(body)) {
16371cb0ef41Sopenharmony_ci    writeIterable({ body, client, request, socket, contentLength, header, expectsPayload })
16381cb0ef41Sopenharmony_ci  } else {
16391cb0ef41Sopenharmony_ci    assert(false)
16401cb0ef41Sopenharmony_ci  }
16411cb0ef41Sopenharmony_ci
16421cb0ef41Sopenharmony_ci  return true
16431cb0ef41Sopenharmony_ci}
16441cb0ef41Sopenharmony_ci
16451cb0ef41Sopenharmony_cifunction writeH2 (client, session, request) {
16461cb0ef41Sopenharmony_ci  const { body, method, path, host, upgrade, expectContinue, signal, headers: reqHeaders } = request
16471cb0ef41Sopenharmony_ci
16481cb0ef41Sopenharmony_ci  let headers
16491cb0ef41Sopenharmony_ci  if (typeof reqHeaders === 'string') headers = Request[kHTTP2CopyHeaders](reqHeaders.trim())
16501cb0ef41Sopenharmony_ci  else headers = reqHeaders
16511cb0ef41Sopenharmony_ci
16521cb0ef41Sopenharmony_ci  if (upgrade) {
16531cb0ef41Sopenharmony_ci    errorRequest(client, request, new Error('Upgrade not supported for H2'))
16541cb0ef41Sopenharmony_ci    return false
16551cb0ef41Sopenharmony_ci  }
16561cb0ef41Sopenharmony_ci
16571cb0ef41Sopenharmony_ci  try {
16581cb0ef41Sopenharmony_ci    // TODO(HTTP/2): Should we call onConnect immediately or on stream ready event?
16591cb0ef41Sopenharmony_ci    request.onConnect((err) => {
16601cb0ef41Sopenharmony_ci      if (request.aborted || request.completed) {
16611cb0ef41Sopenharmony_ci        return
16621cb0ef41Sopenharmony_ci      }
16631cb0ef41Sopenharmony_ci
16641cb0ef41Sopenharmony_ci      errorRequest(client, request, err || new RequestAbortedError())
16651cb0ef41Sopenharmony_ci    })
16661cb0ef41Sopenharmony_ci  } catch (err) {
16671cb0ef41Sopenharmony_ci    errorRequest(client, request, err)
16681cb0ef41Sopenharmony_ci  }
16691cb0ef41Sopenharmony_ci
16701cb0ef41Sopenharmony_ci  if (request.aborted) {
16711cb0ef41Sopenharmony_ci    return false
16721cb0ef41Sopenharmony_ci  }
16731cb0ef41Sopenharmony_ci
16741cb0ef41Sopenharmony_ci  /** @type {import('node:http2').ClientHttp2Stream} */
16751cb0ef41Sopenharmony_ci  let stream
16761cb0ef41Sopenharmony_ci  const h2State = client[kHTTP2SessionState]
16771cb0ef41Sopenharmony_ci
16781cb0ef41Sopenharmony_ci  headers[HTTP2_HEADER_AUTHORITY] = host || client[kHost]
16791cb0ef41Sopenharmony_ci  headers[HTTP2_HEADER_METHOD] = method
16801cb0ef41Sopenharmony_ci
16811cb0ef41Sopenharmony_ci  if (method === 'CONNECT') {
16821cb0ef41Sopenharmony_ci    session.ref()
16831cb0ef41Sopenharmony_ci    // we are already connected, streams are pending, first request
16841cb0ef41Sopenharmony_ci    // will create a new stream. We trigger a request to create the stream and wait until
16851cb0ef41Sopenharmony_ci    // `ready` event is triggered
16861cb0ef41Sopenharmony_ci    // We disabled endStream to allow the user to write to the stream
16871cb0ef41Sopenharmony_ci    stream = session.request(headers, { endStream: false, signal })
16881cb0ef41Sopenharmony_ci
16891cb0ef41Sopenharmony_ci    if (stream.id && !stream.pending) {
16901cb0ef41Sopenharmony_ci      request.onUpgrade(null, null, stream)
16911cb0ef41Sopenharmony_ci      ++h2State.openStreams
16921cb0ef41Sopenharmony_ci    } else {
16931cb0ef41Sopenharmony_ci      stream.once('ready', () => {
16941cb0ef41Sopenharmony_ci        request.onUpgrade(null, null, stream)
16951cb0ef41Sopenharmony_ci        ++h2State.openStreams
16961cb0ef41Sopenharmony_ci      })
16971cb0ef41Sopenharmony_ci    }
16981cb0ef41Sopenharmony_ci
16991cb0ef41Sopenharmony_ci    stream.once('close', () => {
17001cb0ef41Sopenharmony_ci      h2State.openStreams -= 1
17011cb0ef41Sopenharmony_ci      // TODO(HTTP/2): unref only if current streams count is 0
17021cb0ef41Sopenharmony_ci      if (h2State.openStreams === 0) session.unref()
17031cb0ef41Sopenharmony_ci    })
17041cb0ef41Sopenharmony_ci
17051cb0ef41Sopenharmony_ci    return true
17061cb0ef41Sopenharmony_ci  }
17071cb0ef41Sopenharmony_ci
17081cb0ef41Sopenharmony_ci  // https://tools.ietf.org/html/rfc7540#section-8.3
17091cb0ef41Sopenharmony_ci  // :path and :scheme headers must be omited when sending CONNECT
17101cb0ef41Sopenharmony_ci
17111cb0ef41Sopenharmony_ci  headers[HTTP2_HEADER_PATH] = path
17121cb0ef41Sopenharmony_ci  headers[HTTP2_HEADER_SCHEME] = 'https'
17131cb0ef41Sopenharmony_ci
17141cb0ef41Sopenharmony_ci  // https://tools.ietf.org/html/rfc7231#section-4.3.1
17151cb0ef41Sopenharmony_ci  // https://tools.ietf.org/html/rfc7231#section-4.3.2
17161cb0ef41Sopenharmony_ci  // https://tools.ietf.org/html/rfc7231#section-4.3.5
17171cb0ef41Sopenharmony_ci
17181cb0ef41Sopenharmony_ci  // Sending a payload body on a request that does not
17191cb0ef41Sopenharmony_ci  // expect it can cause undefined behavior on some
17201cb0ef41Sopenharmony_ci  // servers and corrupt connection state. Do not
17211cb0ef41Sopenharmony_ci  // re-use the connection for further requests.
17221cb0ef41Sopenharmony_ci
17231cb0ef41Sopenharmony_ci  const expectsPayload = (
17241cb0ef41Sopenharmony_ci    method === 'PUT' ||
17251cb0ef41Sopenharmony_ci    method === 'POST' ||
17261cb0ef41Sopenharmony_ci    method === 'PATCH'
17271cb0ef41Sopenharmony_ci  )
17281cb0ef41Sopenharmony_ci
17291cb0ef41Sopenharmony_ci  if (body && typeof body.read === 'function') {
17301cb0ef41Sopenharmony_ci    // Try to read EOF in order to get length.
17311cb0ef41Sopenharmony_ci    body.read(0)
17321cb0ef41Sopenharmony_ci  }
17331cb0ef41Sopenharmony_ci
17341cb0ef41Sopenharmony_ci  let contentLength = util.bodyLength(body)
17351cb0ef41Sopenharmony_ci
17361cb0ef41Sopenharmony_ci  if (contentLength == null) {
17371cb0ef41Sopenharmony_ci    contentLength = request.contentLength
17381cb0ef41Sopenharmony_ci  }
17391cb0ef41Sopenharmony_ci
17401cb0ef41Sopenharmony_ci  if (contentLength === 0 || !expectsPayload) {
17411cb0ef41Sopenharmony_ci    // https://tools.ietf.org/html/rfc7230#section-3.3.2
17421cb0ef41Sopenharmony_ci    // A user agent SHOULD NOT send a Content-Length header field when
17431cb0ef41Sopenharmony_ci    // the request message does not contain a payload body and the method
17441cb0ef41Sopenharmony_ci    // semantics do not anticipate such a body.
17451cb0ef41Sopenharmony_ci
17461cb0ef41Sopenharmony_ci    contentLength = null
17471cb0ef41Sopenharmony_ci  }
17481cb0ef41Sopenharmony_ci
17491cb0ef41Sopenharmony_ci  // https://github.com/nodejs/undici/issues/2046
17501cb0ef41Sopenharmony_ci  // A user agent may send a Content-Length header with 0 value, this should be allowed.
17511cb0ef41Sopenharmony_ci  if (shouldSendContentLength(method) && contentLength > 0 && request.contentLength != null && request.contentLength !== contentLength) {
17521cb0ef41Sopenharmony_ci    if (client[kStrictContentLength]) {
17531cb0ef41Sopenharmony_ci      errorRequest(client, request, new RequestContentLengthMismatchError())
17541cb0ef41Sopenharmony_ci      return false
17551cb0ef41Sopenharmony_ci    }
17561cb0ef41Sopenharmony_ci
17571cb0ef41Sopenharmony_ci    process.emitWarning(new RequestContentLengthMismatchError())
17581cb0ef41Sopenharmony_ci  }
17591cb0ef41Sopenharmony_ci
17601cb0ef41Sopenharmony_ci  if (contentLength != null) {
17611cb0ef41Sopenharmony_ci    assert(body, 'no body must not have content length')
17621cb0ef41Sopenharmony_ci    headers[HTTP2_HEADER_CONTENT_LENGTH] = `${contentLength}`
17631cb0ef41Sopenharmony_ci  }
17641cb0ef41Sopenharmony_ci
17651cb0ef41Sopenharmony_ci  session.ref()
17661cb0ef41Sopenharmony_ci
17671cb0ef41Sopenharmony_ci  const shouldEndStream = method === 'GET' || method === 'HEAD'
17681cb0ef41Sopenharmony_ci  if (expectContinue) {
17691cb0ef41Sopenharmony_ci    headers[HTTP2_HEADER_EXPECT] = '100-continue'
17701cb0ef41Sopenharmony_ci    stream = session.request(headers, { endStream: shouldEndStream, signal })
17711cb0ef41Sopenharmony_ci
17721cb0ef41Sopenharmony_ci    stream.once('continue', writeBodyH2)
17731cb0ef41Sopenharmony_ci  } else {
17741cb0ef41Sopenharmony_ci    stream = session.request(headers, {
17751cb0ef41Sopenharmony_ci      endStream: shouldEndStream,
17761cb0ef41Sopenharmony_ci      signal
17771cb0ef41Sopenharmony_ci    })
17781cb0ef41Sopenharmony_ci    writeBodyH2()
17791cb0ef41Sopenharmony_ci  }
17801cb0ef41Sopenharmony_ci
17811cb0ef41Sopenharmony_ci  // Increment counter as we have new several streams open
17821cb0ef41Sopenharmony_ci  ++h2State.openStreams
17831cb0ef41Sopenharmony_ci
17841cb0ef41Sopenharmony_ci  stream.once('response', headers => {
17851cb0ef41Sopenharmony_ci    const { [HTTP2_HEADER_STATUS]: statusCode, ...realHeaders } = headers
17861cb0ef41Sopenharmony_ci
17871cb0ef41Sopenharmony_ci    if (request.onHeaders(Number(statusCode), realHeaders, stream.resume.bind(stream), '') === false) {
17881cb0ef41Sopenharmony_ci      stream.pause()
17891cb0ef41Sopenharmony_ci    }
17901cb0ef41Sopenharmony_ci  })
17911cb0ef41Sopenharmony_ci
17921cb0ef41Sopenharmony_ci  stream.once('end', () => {
17931cb0ef41Sopenharmony_ci    request.onComplete([])
17941cb0ef41Sopenharmony_ci  })
17951cb0ef41Sopenharmony_ci
17961cb0ef41Sopenharmony_ci  stream.on('data', (chunk) => {
17971cb0ef41Sopenharmony_ci    if (request.onData(chunk) === false) {
17981cb0ef41Sopenharmony_ci      stream.pause()
17991cb0ef41Sopenharmony_ci    }
18001cb0ef41Sopenharmony_ci  })
18011cb0ef41Sopenharmony_ci
18021cb0ef41Sopenharmony_ci  stream.once('close', () => {
18031cb0ef41Sopenharmony_ci    h2State.openStreams -= 1
18041cb0ef41Sopenharmony_ci    // TODO(HTTP/2): unref only if current streams count is 0
18051cb0ef41Sopenharmony_ci    if (h2State.openStreams === 0) {
18061cb0ef41Sopenharmony_ci      session.unref()
18071cb0ef41Sopenharmony_ci    }
18081cb0ef41Sopenharmony_ci  })
18091cb0ef41Sopenharmony_ci
18101cb0ef41Sopenharmony_ci  stream.once('error', function (err) {
18111cb0ef41Sopenharmony_ci    if (client[kHTTP2Session] && !client[kHTTP2Session].destroyed && !this.closed && !this.destroyed) {
18121cb0ef41Sopenharmony_ci      h2State.streams -= 1
18131cb0ef41Sopenharmony_ci      util.destroy(stream, err)
18141cb0ef41Sopenharmony_ci    }
18151cb0ef41Sopenharmony_ci  })
18161cb0ef41Sopenharmony_ci
18171cb0ef41Sopenharmony_ci  stream.once('frameError', (type, code) => {
18181cb0ef41Sopenharmony_ci    const err = new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`)
18191cb0ef41Sopenharmony_ci    errorRequest(client, request, err)
18201cb0ef41Sopenharmony_ci
18211cb0ef41Sopenharmony_ci    if (client[kHTTP2Session] && !client[kHTTP2Session].destroyed && !this.closed && !this.destroyed) {
18221cb0ef41Sopenharmony_ci      h2State.streams -= 1
18231cb0ef41Sopenharmony_ci      util.destroy(stream, err)
18241cb0ef41Sopenharmony_ci    }
18251cb0ef41Sopenharmony_ci  })
18261cb0ef41Sopenharmony_ci
18271cb0ef41Sopenharmony_ci  // stream.on('aborted', () => {
18281cb0ef41Sopenharmony_ci  //   // TODO(HTTP/2): Support aborted
18291cb0ef41Sopenharmony_ci  // })
18301cb0ef41Sopenharmony_ci
18311cb0ef41Sopenharmony_ci  // stream.on('timeout', () => {
18321cb0ef41Sopenharmony_ci  //   // TODO(HTTP/2): Support timeout
18331cb0ef41Sopenharmony_ci  // })
18341cb0ef41Sopenharmony_ci
18351cb0ef41Sopenharmony_ci  // stream.on('push', headers => {
18361cb0ef41Sopenharmony_ci  //   // TODO(HTTP/2): Suppor push
18371cb0ef41Sopenharmony_ci  // })
18381cb0ef41Sopenharmony_ci
18391cb0ef41Sopenharmony_ci  // stream.on('trailers', headers => {
18401cb0ef41Sopenharmony_ci  //   // TODO(HTTP/2): Support trailers
18411cb0ef41Sopenharmony_ci  // })
18421cb0ef41Sopenharmony_ci
18431cb0ef41Sopenharmony_ci  return true
18441cb0ef41Sopenharmony_ci
18451cb0ef41Sopenharmony_ci  function writeBodyH2 () {
18461cb0ef41Sopenharmony_ci    /* istanbul ignore else: assertion */
18471cb0ef41Sopenharmony_ci    if (!body) {
18481cb0ef41Sopenharmony_ci      request.onRequestSent()
18491cb0ef41Sopenharmony_ci    } else if (util.isBuffer(body)) {
18501cb0ef41Sopenharmony_ci      assert(contentLength === body.byteLength, 'buffer body must have content length')
18511cb0ef41Sopenharmony_ci      stream.cork()
18521cb0ef41Sopenharmony_ci      stream.write(body)
18531cb0ef41Sopenharmony_ci      stream.uncork()
18541cb0ef41Sopenharmony_ci      stream.end()
18551cb0ef41Sopenharmony_ci      request.onBodySent(body)
18561cb0ef41Sopenharmony_ci      request.onRequestSent()
18571cb0ef41Sopenharmony_ci    } else if (util.isBlobLike(body)) {
18581cb0ef41Sopenharmony_ci      if (typeof body.stream === 'function') {
18591cb0ef41Sopenharmony_ci        writeIterable({
18601cb0ef41Sopenharmony_ci          client,
18611cb0ef41Sopenharmony_ci          request,
18621cb0ef41Sopenharmony_ci          contentLength,
18631cb0ef41Sopenharmony_ci          h2stream: stream,
18641cb0ef41Sopenharmony_ci          expectsPayload,
18651cb0ef41Sopenharmony_ci          body: body.stream(),
18661cb0ef41Sopenharmony_ci          socket: client[kSocket],
18671cb0ef41Sopenharmony_ci          header: ''
18681cb0ef41Sopenharmony_ci        })
18691cb0ef41Sopenharmony_ci      } else {
18701cb0ef41Sopenharmony_ci        writeBlob({
18711cb0ef41Sopenharmony_ci          body,
18721cb0ef41Sopenharmony_ci          client,
18731cb0ef41Sopenharmony_ci          request,
18741cb0ef41Sopenharmony_ci          contentLength,
18751cb0ef41Sopenharmony_ci          expectsPayload,
18761cb0ef41Sopenharmony_ci          h2stream: stream,
18771cb0ef41Sopenharmony_ci          header: '',
18781cb0ef41Sopenharmony_ci          socket: client[kSocket]
18791cb0ef41Sopenharmony_ci        })
18801cb0ef41Sopenharmony_ci      }
18811cb0ef41Sopenharmony_ci    } else if (util.isStream(body)) {
18821cb0ef41Sopenharmony_ci      writeStream({
18831cb0ef41Sopenharmony_ci        body,
18841cb0ef41Sopenharmony_ci        client,
18851cb0ef41Sopenharmony_ci        request,
18861cb0ef41Sopenharmony_ci        contentLength,
18871cb0ef41Sopenharmony_ci        expectsPayload,
18881cb0ef41Sopenharmony_ci        socket: client[kSocket],
18891cb0ef41Sopenharmony_ci        h2stream: stream,
18901cb0ef41Sopenharmony_ci        header: ''
18911cb0ef41Sopenharmony_ci      })
18921cb0ef41Sopenharmony_ci    } else if (util.isIterable(body)) {
18931cb0ef41Sopenharmony_ci      writeIterable({
18941cb0ef41Sopenharmony_ci        body,
18951cb0ef41Sopenharmony_ci        client,
18961cb0ef41Sopenharmony_ci        request,
18971cb0ef41Sopenharmony_ci        contentLength,
18981cb0ef41Sopenharmony_ci        expectsPayload,
18991cb0ef41Sopenharmony_ci        header: '',
19001cb0ef41Sopenharmony_ci        h2stream: stream,
19011cb0ef41Sopenharmony_ci        socket: client[kSocket]
19021cb0ef41Sopenharmony_ci      })
19031cb0ef41Sopenharmony_ci    } else {
19041cb0ef41Sopenharmony_ci      assert(false)
19051cb0ef41Sopenharmony_ci    }
19061cb0ef41Sopenharmony_ci  }
19071cb0ef41Sopenharmony_ci}
19081cb0ef41Sopenharmony_ci
19091cb0ef41Sopenharmony_cifunction writeStream ({ h2stream, body, client, request, socket, contentLength, header, expectsPayload }) {
19101cb0ef41Sopenharmony_ci  assert(contentLength !== 0 || client[kRunning] === 0, 'stream body cannot be pipelined')
19111cb0ef41Sopenharmony_ci
19121cb0ef41Sopenharmony_ci  if (client[kHTTPConnVersion] === 'h2') {
19131cb0ef41Sopenharmony_ci    // For HTTP/2, is enough to pipe the stream
19141cb0ef41Sopenharmony_ci    const pipe = pipeline(
19151cb0ef41Sopenharmony_ci      body,
19161cb0ef41Sopenharmony_ci      h2stream,
19171cb0ef41Sopenharmony_ci      (err) => {
19181cb0ef41Sopenharmony_ci        if (err) {
19191cb0ef41Sopenharmony_ci          util.destroy(body, err)
19201cb0ef41Sopenharmony_ci          util.destroy(h2stream, err)
19211cb0ef41Sopenharmony_ci        } else {
19221cb0ef41Sopenharmony_ci          request.onRequestSent()
19231cb0ef41Sopenharmony_ci        }
19241cb0ef41Sopenharmony_ci      }
19251cb0ef41Sopenharmony_ci    )
19261cb0ef41Sopenharmony_ci
19271cb0ef41Sopenharmony_ci    pipe.on('data', onPipeData)
19281cb0ef41Sopenharmony_ci    pipe.once('end', () => {
19291cb0ef41Sopenharmony_ci      pipe.removeListener('data', onPipeData)
19301cb0ef41Sopenharmony_ci      util.destroy(pipe)
19311cb0ef41Sopenharmony_ci    })
19321cb0ef41Sopenharmony_ci
19331cb0ef41Sopenharmony_ci    function onPipeData (chunk) {
19341cb0ef41Sopenharmony_ci      request.onBodySent(chunk)
19351cb0ef41Sopenharmony_ci    }
19361cb0ef41Sopenharmony_ci
19371cb0ef41Sopenharmony_ci    return
19381cb0ef41Sopenharmony_ci  }
19391cb0ef41Sopenharmony_ci
19401cb0ef41Sopenharmony_ci  let finished = false
19411cb0ef41Sopenharmony_ci
19421cb0ef41Sopenharmony_ci  const writer = new AsyncWriter({ socket, request, contentLength, client, expectsPayload, header })
19431cb0ef41Sopenharmony_ci
19441cb0ef41Sopenharmony_ci  const onData = function (chunk) {
19451cb0ef41Sopenharmony_ci    if (finished) {
19461cb0ef41Sopenharmony_ci      return
19471cb0ef41Sopenharmony_ci    }
19481cb0ef41Sopenharmony_ci
19491cb0ef41Sopenharmony_ci    try {
19501cb0ef41Sopenharmony_ci      if (!writer.write(chunk) && this.pause) {
19511cb0ef41Sopenharmony_ci        this.pause()
19521cb0ef41Sopenharmony_ci      }
19531cb0ef41Sopenharmony_ci    } catch (err) {
19541cb0ef41Sopenharmony_ci      util.destroy(this, err)
19551cb0ef41Sopenharmony_ci    }
19561cb0ef41Sopenharmony_ci  }
19571cb0ef41Sopenharmony_ci  const onDrain = function () {
19581cb0ef41Sopenharmony_ci    if (finished) {
19591cb0ef41Sopenharmony_ci      return
19601cb0ef41Sopenharmony_ci    }
19611cb0ef41Sopenharmony_ci
19621cb0ef41Sopenharmony_ci    if (body.resume) {
19631cb0ef41Sopenharmony_ci      body.resume()
19641cb0ef41Sopenharmony_ci    }
19651cb0ef41Sopenharmony_ci  }
19661cb0ef41Sopenharmony_ci  const onAbort = function () {
19671cb0ef41Sopenharmony_ci    if (finished) {
19681cb0ef41Sopenharmony_ci      return
19691cb0ef41Sopenharmony_ci    }
19701cb0ef41Sopenharmony_ci    const err = new RequestAbortedError()
19711cb0ef41Sopenharmony_ci    queueMicrotask(() => onFinished(err))
19721cb0ef41Sopenharmony_ci  }
19731cb0ef41Sopenharmony_ci  const onFinished = function (err) {
19741cb0ef41Sopenharmony_ci    if (finished) {
19751cb0ef41Sopenharmony_ci      return
19761cb0ef41Sopenharmony_ci    }
19771cb0ef41Sopenharmony_ci
19781cb0ef41Sopenharmony_ci    finished = true
19791cb0ef41Sopenharmony_ci
19801cb0ef41Sopenharmony_ci    assert(socket.destroyed || (socket[kWriting] && client[kRunning] <= 1))
19811cb0ef41Sopenharmony_ci
19821cb0ef41Sopenharmony_ci    socket
19831cb0ef41Sopenharmony_ci      .off('drain', onDrain)
19841cb0ef41Sopenharmony_ci      .off('error', onFinished)
19851cb0ef41Sopenharmony_ci
19861cb0ef41Sopenharmony_ci    body
19871cb0ef41Sopenharmony_ci      .removeListener('data', onData)
19881cb0ef41Sopenharmony_ci      .removeListener('end', onFinished)
19891cb0ef41Sopenharmony_ci      .removeListener('error', onFinished)
19901cb0ef41Sopenharmony_ci      .removeListener('close', onAbort)
19911cb0ef41Sopenharmony_ci
19921cb0ef41Sopenharmony_ci    if (!err) {
19931cb0ef41Sopenharmony_ci      try {
19941cb0ef41Sopenharmony_ci        writer.end()
19951cb0ef41Sopenharmony_ci      } catch (er) {
19961cb0ef41Sopenharmony_ci        err = er
19971cb0ef41Sopenharmony_ci      }
19981cb0ef41Sopenharmony_ci    }
19991cb0ef41Sopenharmony_ci
20001cb0ef41Sopenharmony_ci    writer.destroy(err)
20011cb0ef41Sopenharmony_ci
20021cb0ef41Sopenharmony_ci    if (err && (err.code !== 'UND_ERR_INFO' || err.message !== 'reset')) {
20031cb0ef41Sopenharmony_ci      util.destroy(body, err)
20041cb0ef41Sopenharmony_ci    } else {
20051cb0ef41Sopenharmony_ci      util.destroy(body)
20061cb0ef41Sopenharmony_ci    }
20071cb0ef41Sopenharmony_ci  }
20081cb0ef41Sopenharmony_ci
20091cb0ef41Sopenharmony_ci  body
20101cb0ef41Sopenharmony_ci    .on('data', onData)
20111cb0ef41Sopenharmony_ci    .on('end', onFinished)
20121cb0ef41Sopenharmony_ci    .on('error', onFinished)
20131cb0ef41Sopenharmony_ci    .on('close', onAbort)
20141cb0ef41Sopenharmony_ci
20151cb0ef41Sopenharmony_ci  if (body.resume) {
20161cb0ef41Sopenharmony_ci    body.resume()
20171cb0ef41Sopenharmony_ci  }
20181cb0ef41Sopenharmony_ci
20191cb0ef41Sopenharmony_ci  socket
20201cb0ef41Sopenharmony_ci    .on('drain', onDrain)
20211cb0ef41Sopenharmony_ci    .on('error', onFinished)
20221cb0ef41Sopenharmony_ci}
20231cb0ef41Sopenharmony_ci
20241cb0ef41Sopenharmony_ciasync function writeBlob ({ h2stream, body, client, request, socket, contentLength, header, expectsPayload }) {
20251cb0ef41Sopenharmony_ci  assert(contentLength === body.size, 'blob body must have content length')
20261cb0ef41Sopenharmony_ci
20271cb0ef41Sopenharmony_ci  const isH2 = client[kHTTPConnVersion] === 'h2'
20281cb0ef41Sopenharmony_ci  try {
20291cb0ef41Sopenharmony_ci    if (contentLength != null && contentLength !== body.size) {
20301cb0ef41Sopenharmony_ci      throw new RequestContentLengthMismatchError()
20311cb0ef41Sopenharmony_ci    }
20321cb0ef41Sopenharmony_ci
20331cb0ef41Sopenharmony_ci    const buffer = Buffer.from(await body.arrayBuffer())
20341cb0ef41Sopenharmony_ci
20351cb0ef41Sopenharmony_ci    if (isH2) {
20361cb0ef41Sopenharmony_ci      h2stream.cork()
20371cb0ef41Sopenharmony_ci      h2stream.write(buffer)
20381cb0ef41Sopenharmony_ci      h2stream.uncork()
20391cb0ef41Sopenharmony_ci    } else {
20401cb0ef41Sopenharmony_ci      socket.cork()
20411cb0ef41Sopenharmony_ci      socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'latin1')
20421cb0ef41Sopenharmony_ci      socket.write(buffer)
20431cb0ef41Sopenharmony_ci      socket.uncork()
20441cb0ef41Sopenharmony_ci    }
20451cb0ef41Sopenharmony_ci
20461cb0ef41Sopenharmony_ci    request.onBodySent(buffer)
20471cb0ef41Sopenharmony_ci    request.onRequestSent()
20481cb0ef41Sopenharmony_ci
20491cb0ef41Sopenharmony_ci    if (!expectsPayload) {
20501cb0ef41Sopenharmony_ci      socket[kReset] = true
20511cb0ef41Sopenharmony_ci    }
20521cb0ef41Sopenharmony_ci
20531cb0ef41Sopenharmony_ci    resume(client)
20541cb0ef41Sopenharmony_ci  } catch (err) {
20551cb0ef41Sopenharmony_ci    util.destroy(isH2 ? h2stream : socket, err)
20561cb0ef41Sopenharmony_ci  }
20571cb0ef41Sopenharmony_ci}
20581cb0ef41Sopenharmony_ci
20591cb0ef41Sopenharmony_ciasync function writeIterable ({ h2stream, body, client, request, socket, contentLength, header, expectsPayload }) {
20601cb0ef41Sopenharmony_ci  assert(contentLength !== 0 || client[kRunning] === 0, 'iterator body cannot be pipelined')
20611cb0ef41Sopenharmony_ci
20621cb0ef41Sopenharmony_ci  let callback = null
20631cb0ef41Sopenharmony_ci  function onDrain () {
20641cb0ef41Sopenharmony_ci    if (callback) {
20651cb0ef41Sopenharmony_ci      const cb = callback
20661cb0ef41Sopenharmony_ci      callback = null
20671cb0ef41Sopenharmony_ci      cb()
20681cb0ef41Sopenharmony_ci    }
20691cb0ef41Sopenharmony_ci  }
20701cb0ef41Sopenharmony_ci
20711cb0ef41Sopenharmony_ci  const waitForDrain = () => new Promise((resolve, reject) => {
20721cb0ef41Sopenharmony_ci    assert(callback === null)
20731cb0ef41Sopenharmony_ci
20741cb0ef41Sopenharmony_ci    if (socket[kError]) {
20751cb0ef41Sopenharmony_ci      reject(socket[kError])
20761cb0ef41Sopenharmony_ci    } else {
20771cb0ef41Sopenharmony_ci      callback = resolve
20781cb0ef41Sopenharmony_ci    }
20791cb0ef41Sopenharmony_ci  })
20801cb0ef41Sopenharmony_ci
20811cb0ef41Sopenharmony_ci  if (client[kHTTPConnVersion] === 'h2') {
20821cb0ef41Sopenharmony_ci    h2stream
20831cb0ef41Sopenharmony_ci      .on('close', onDrain)
20841cb0ef41Sopenharmony_ci      .on('drain', onDrain)
20851cb0ef41Sopenharmony_ci
20861cb0ef41Sopenharmony_ci    try {
20871cb0ef41Sopenharmony_ci      // It's up to the user to somehow abort the async iterable.
20881cb0ef41Sopenharmony_ci      for await (const chunk of body) {
20891cb0ef41Sopenharmony_ci        if (socket[kError]) {
20901cb0ef41Sopenharmony_ci          throw socket[kError]
20911cb0ef41Sopenharmony_ci        }
20921cb0ef41Sopenharmony_ci
20931cb0ef41Sopenharmony_ci        const res = h2stream.write(chunk)
20941cb0ef41Sopenharmony_ci        request.onBodySent(chunk)
20951cb0ef41Sopenharmony_ci        if (!res) {
20961cb0ef41Sopenharmony_ci          await waitForDrain()
20971cb0ef41Sopenharmony_ci        }
20981cb0ef41Sopenharmony_ci      }
20991cb0ef41Sopenharmony_ci    } catch (err) {
21001cb0ef41Sopenharmony_ci      h2stream.destroy(err)
21011cb0ef41Sopenharmony_ci    } finally {
21021cb0ef41Sopenharmony_ci      request.onRequestSent()
21031cb0ef41Sopenharmony_ci      h2stream.end()
21041cb0ef41Sopenharmony_ci      h2stream
21051cb0ef41Sopenharmony_ci        .off('close', onDrain)
21061cb0ef41Sopenharmony_ci        .off('drain', onDrain)
21071cb0ef41Sopenharmony_ci    }
21081cb0ef41Sopenharmony_ci
21091cb0ef41Sopenharmony_ci    return
21101cb0ef41Sopenharmony_ci  }
21111cb0ef41Sopenharmony_ci
21121cb0ef41Sopenharmony_ci  socket
21131cb0ef41Sopenharmony_ci    .on('close', onDrain)
21141cb0ef41Sopenharmony_ci    .on('drain', onDrain)
21151cb0ef41Sopenharmony_ci
21161cb0ef41Sopenharmony_ci  const writer = new AsyncWriter({ socket, request, contentLength, client, expectsPayload, header })
21171cb0ef41Sopenharmony_ci  try {
21181cb0ef41Sopenharmony_ci    // It's up to the user to somehow abort the async iterable.
21191cb0ef41Sopenharmony_ci    for await (const chunk of body) {
21201cb0ef41Sopenharmony_ci      if (socket[kError]) {
21211cb0ef41Sopenharmony_ci        throw socket[kError]
21221cb0ef41Sopenharmony_ci      }
21231cb0ef41Sopenharmony_ci
21241cb0ef41Sopenharmony_ci      if (!writer.write(chunk)) {
21251cb0ef41Sopenharmony_ci        await waitForDrain()
21261cb0ef41Sopenharmony_ci      }
21271cb0ef41Sopenharmony_ci    }
21281cb0ef41Sopenharmony_ci
21291cb0ef41Sopenharmony_ci    writer.end()
21301cb0ef41Sopenharmony_ci  } catch (err) {
21311cb0ef41Sopenharmony_ci    writer.destroy(err)
21321cb0ef41Sopenharmony_ci  } finally {
21331cb0ef41Sopenharmony_ci    socket
21341cb0ef41Sopenharmony_ci      .off('close', onDrain)
21351cb0ef41Sopenharmony_ci      .off('drain', onDrain)
21361cb0ef41Sopenharmony_ci  }
21371cb0ef41Sopenharmony_ci}
21381cb0ef41Sopenharmony_ci
21391cb0ef41Sopenharmony_ciclass AsyncWriter {
21401cb0ef41Sopenharmony_ci  constructor ({ socket, request, contentLength, client, expectsPayload, header }) {
21411cb0ef41Sopenharmony_ci    this.socket = socket
21421cb0ef41Sopenharmony_ci    this.request = request
21431cb0ef41Sopenharmony_ci    this.contentLength = contentLength
21441cb0ef41Sopenharmony_ci    this.client = client
21451cb0ef41Sopenharmony_ci    this.bytesWritten = 0
21461cb0ef41Sopenharmony_ci    this.expectsPayload = expectsPayload
21471cb0ef41Sopenharmony_ci    this.header = header
21481cb0ef41Sopenharmony_ci
21491cb0ef41Sopenharmony_ci    socket[kWriting] = true
21501cb0ef41Sopenharmony_ci  }
21511cb0ef41Sopenharmony_ci
21521cb0ef41Sopenharmony_ci  write (chunk) {
21531cb0ef41Sopenharmony_ci    const { socket, request, contentLength, client, bytesWritten, expectsPayload, header } = this
21541cb0ef41Sopenharmony_ci
21551cb0ef41Sopenharmony_ci    if (socket[kError]) {
21561cb0ef41Sopenharmony_ci      throw socket[kError]
21571cb0ef41Sopenharmony_ci    }
21581cb0ef41Sopenharmony_ci
21591cb0ef41Sopenharmony_ci    if (socket.destroyed) {
21601cb0ef41Sopenharmony_ci      return false
21611cb0ef41Sopenharmony_ci    }
21621cb0ef41Sopenharmony_ci
21631cb0ef41Sopenharmony_ci    const len = Buffer.byteLength(chunk)
21641cb0ef41Sopenharmony_ci    if (!len) {
21651cb0ef41Sopenharmony_ci      return true
21661cb0ef41Sopenharmony_ci    }
21671cb0ef41Sopenharmony_ci
21681cb0ef41Sopenharmony_ci    // We should defer writing chunks.
21691cb0ef41Sopenharmony_ci    if (contentLength !== null && bytesWritten + len > contentLength) {
21701cb0ef41Sopenharmony_ci      if (client[kStrictContentLength]) {
21711cb0ef41Sopenharmony_ci        throw new RequestContentLengthMismatchError()
21721cb0ef41Sopenharmony_ci      }
21731cb0ef41Sopenharmony_ci
21741cb0ef41Sopenharmony_ci      process.emitWarning(new RequestContentLengthMismatchError())
21751cb0ef41Sopenharmony_ci    }
21761cb0ef41Sopenharmony_ci
21771cb0ef41Sopenharmony_ci    socket.cork()
21781cb0ef41Sopenharmony_ci
21791cb0ef41Sopenharmony_ci    if (bytesWritten === 0) {
21801cb0ef41Sopenharmony_ci      if (!expectsPayload) {
21811cb0ef41Sopenharmony_ci        socket[kReset] = true
21821cb0ef41Sopenharmony_ci      }
21831cb0ef41Sopenharmony_ci
21841cb0ef41Sopenharmony_ci      if (contentLength === null) {
21851cb0ef41Sopenharmony_ci        socket.write(`${header}transfer-encoding: chunked\r\n`, 'latin1')
21861cb0ef41Sopenharmony_ci      } else {
21871cb0ef41Sopenharmony_ci        socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'latin1')
21881cb0ef41Sopenharmony_ci      }
21891cb0ef41Sopenharmony_ci    }
21901cb0ef41Sopenharmony_ci
21911cb0ef41Sopenharmony_ci    if (contentLength === null) {
21921cb0ef41Sopenharmony_ci      socket.write(`\r\n${len.toString(16)}\r\n`, 'latin1')
21931cb0ef41Sopenharmony_ci    }
21941cb0ef41Sopenharmony_ci
21951cb0ef41Sopenharmony_ci    this.bytesWritten += len
21961cb0ef41Sopenharmony_ci
21971cb0ef41Sopenharmony_ci    const ret = socket.write(chunk)
21981cb0ef41Sopenharmony_ci
21991cb0ef41Sopenharmony_ci    socket.uncork()
22001cb0ef41Sopenharmony_ci
22011cb0ef41Sopenharmony_ci    request.onBodySent(chunk)
22021cb0ef41Sopenharmony_ci
22031cb0ef41Sopenharmony_ci    if (!ret) {
22041cb0ef41Sopenharmony_ci      if (socket[kParser].timeout && socket[kParser].timeoutType === TIMEOUT_HEADERS) {
22051cb0ef41Sopenharmony_ci        // istanbul ignore else: only for jest
22061cb0ef41Sopenharmony_ci        if (socket[kParser].timeout.refresh) {
22071cb0ef41Sopenharmony_ci          socket[kParser].timeout.refresh()
22081cb0ef41Sopenharmony_ci        }
22091cb0ef41Sopenharmony_ci      }
22101cb0ef41Sopenharmony_ci    }
22111cb0ef41Sopenharmony_ci
22121cb0ef41Sopenharmony_ci    return ret
22131cb0ef41Sopenharmony_ci  }
22141cb0ef41Sopenharmony_ci
22151cb0ef41Sopenharmony_ci  end () {
22161cb0ef41Sopenharmony_ci    const { socket, contentLength, client, bytesWritten, expectsPayload, header, request } = this
22171cb0ef41Sopenharmony_ci    request.onRequestSent()
22181cb0ef41Sopenharmony_ci
22191cb0ef41Sopenharmony_ci    socket[kWriting] = false
22201cb0ef41Sopenharmony_ci
22211cb0ef41Sopenharmony_ci    if (socket[kError]) {
22221cb0ef41Sopenharmony_ci      throw socket[kError]
22231cb0ef41Sopenharmony_ci    }
22241cb0ef41Sopenharmony_ci
22251cb0ef41Sopenharmony_ci    if (socket.destroyed) {
22261cb0ef41Sopenharmony_ci      return
22271cb0ef41Sopenharmony_ci    }
22281cb0ef41Sopenharmony_ci
22291cb0ef41Sopenharmony_ci    if (bytesWritten === 0) {
22301cb0ef41Sopenharmony_ci      if (expectsPayload) {
22311cb0ef41Sopenharmony_ci        // https://tools.ietf.org/html/rfc7230#section-3.3.2
22321cb0ef41Sopenharmony_ci        // A user agent SHOULD send a Content-Length in a request message when
22331cb0ef41Sopenharmony_ci        // no Transfer-Encoding is sent and the request method defines a meaning
22341cb0ef41Sopenharmony_ci        // for an enclosed payload body.
22351cb0ef41Sopenharmony_ci
22361cb0ef41Sopenharmony_ci        socket.write(`${header}content-length: 0\r\n\r\n`, 'latin1')
22371cb0ef41Sopenharmony_ci      } else {
22381cb0ef41Sopenharmony_ci        socket.write(`${header}\r\n`, 'latin1')
22391cb0ef41Sopenharmony_ci      }
22401cb0ef41Sopenharmony_ci    } else if (contentLength === null) {
22411cb0ef41Sopenharmony_ci      socket.write('\r\n0\r\n\r\n', 'latin1')
22421cb0ef41Sopenharmony_ci    }
22431cb0ef41Sopenharmony_ci
22441cb0ef41Sopenharmony_ci    if (contentLength !== null && bytesWritten !== contentLength) {
22451cb0ef41Sopenharmony_ci      if (client[kStrictContentLength]) {
22461cb0ef41Sopenharmony_ci        throw new RequestContentLengthMismatchError()
22471cb0ef41Sopenharmony_ci      } else {
22481cb0ef41Sopenharmony_ci        process.emitWarning(new RequestContentLengthMismatchError())
22491cb0ef41Sopenharmony_ci      }
22501cb0ef41Sopenharmony_ci    }
22511cb0ef41Sopenharmony_ci
22521cb0ef41Sopenharmony_ci    if (socket[kParser].timeout && socket[kParser].timeoutType === TIMEOUT_HEADERS) {
22531cb0ef41Sopenharmony_ci      // istanbul ignore else: only for jest
22541cb0ef41Sopenharmony_ci      if (socket[kParser].timeout.refresh) {
22551cb0ef41Sopenharmony_ci        socket[kParser].timeout.refresh()
22561cb0ef41Sopenharmony_ci      }
22571cb0ef41Sopenharmony_ci    }
22581cb0ef41Sopenharmony_ci
22591cb0ef41Sopenharmony_ci    resume(client)
22601cb0ef41Sopenharmony_ci  }
22611cb0ef41Sopenharmony_ci
22621cb0ef41Sopenharmony_ci  destroy (err) {
22631cb0ef41Sopenharmony_ci    const { socket, client } = this
22641cb0ef41Sopenharmony_ci
22651cb0ef41Sopenharmony_ci    socket[kWriting] = false
22661cb0ef41Sopenharmony_ci
22671cb0ef41Sopenharmony_ci    if (err) {
22681cb0ef41Sopenharmony_ci      assert(client[kRunning] <= 1, 'pipeline should only contain this request')
22691cb0ef41Sopenharmony_ci      util.destroy(socket, err)
22701cb0ef41Sopenharmony_ci    }
22711cb0ef41Sopenharmony_ci  }
22721cb0ef41Sopenharmony_ci}
22731cb0ef41Sopenharmony_ci
22741cb0ef41Sopenharmony_cifunction errorRequest (client, request, err) {
22751cb0ef41Sopenharmony_ci  try {
22761cb0ef41Sopenharmony_ci    request.onError(err)
22771cb0ef41Sopenharmony_ci    assert(request.aborted)
22781cb0ef41Sopenharmony_ci  } catch (err) {
22791cb0ef41Sopenharmony_ci    client.emit('error', err)
22801cb0ef41Sopenharmony_ci  }
22811cb0ef41Sopenharmony_ci}
22821cb0ef41Sopenharmony_ci
22831cb0ef41Sopenharmony_cimodule.exports = Client
2284