aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/node_modules/undici/lib/dispatcher/client-h2.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/undici/lib/dispatcher/client-h2.js')
-rw-r--r--node_modules/undici/lib/dispatcher/client-h2.js88
1 files changed, 70 insertions, 18 deletions
diff --git a/node_modules/undici/lib/dispatcher/client-h2.js b/node_modules/undici/lib/dispatcher/client-h2.js
index 4a52eff..bb8eda8 100644
--- a/node_modules/undici/lib/dispatcher/client-h2.js
+++ b/node_modules/undici/lib/dispatcher/client-h2.js
@@ -1,6 +1,7 @@
'use strict'
const assert = require('node:assert')
+const { errorMonitor } = require('node:events')
const { pipeline } = require('node:stream')
const util = require('../core/util.js')
const {
@@ -77,6 +78,15 @@ function parseH2Headers (headers) {
return result
}
+/**
+ * @param {import('node:http2').IncomingHttpHeaders} headers
+ * @returns {Buffer[]}
+ */
+function parseH2ResponseHeaders (headers) {
+ const { [HTTP2_HEADER_STATUS]: _statusCode, ...realHeaders } = headers
+ return parseH2Headers(realHeaders)
+}
+
async function connectH2 (client, socket) {
client[kSocket] = socket
@@ -297,22 +307,32 @@ function writeH2 (client, request) {
headers[HTTP2_HEADER_AUTHORITY] = host || `${hostname}${port ? `:${port}` : ''}`
headers[HTTP2_HEADER_METHOD] = method
- const abort = (err) => {
- if (request.aborted || request.completed) {
+ /**
+ * @param {Error} [error]
+ */
+ const abort = (error) => {
+ if (request.aborted) {
+ return
+ }
+
+ if (request.completed) {
+ if (method === 'CONNECT' && stream != null) {
+ util.destroy(stream, error || new RequestAbortedError())
+ }
return
}
- err = err || new RequestAbortedError()
+ error = error || new RequestAbortedError()
- util.errorRequest(client, request, err)
+ util.errorRequest(client, request, error)
if (stream != null) {
- util.destroy(stream, err)
+ util.destroy(stream, error)
}
// We do not destroy the socket as we can continue using the session
// the stream get's destroyed and the session remains to create new streams
- util.destroy(body, err)
+ util.destroy(body, error)
client[kQueue][client[kRunningIdx]++] = null
client[kResume]()
}
@@ -331,25 +351,57 @@ function writeH2 (client, request) {
if (method === 'CONNECT') {
session.ref()
- // We are already connected, streams are pending, first request
- // will create a new stream. We trigger a request to create the stream and wait until
- // `ready` event is triggered
// We disabled endStream to allow the user to write to the stream
stream = session.request(headers, { endStream: false, signal })
+ let upgradeResponseFinished = false
- if (stream.id && !stream.pending) {
- request.onUpgrade(null, null, stream)
- ++session[kOpenStreams]
- client[kQueue][client[kRunningIdx]++] = null
- } else {
- stream.once('ready', () => {
+ /**
+ * @param {import('node:http2').IncomingHttpHeaders} headers
+ */
+ const onResponse = (headers) => {
+ upgradeResponseFinished = true
+ stream.off(errorMonitor, onUpgradeError)
+ request.onUpgradeResponse(Number(headers[HTTP2_HEADER_STATUS]), headers, parseH2ResponseHeaders)
+ }
+
+ /**
+ * @param {Error} error
+ */
+ const onUpgradeError = (error) => {
+ upgradeResponseFinished = true
+ stream.off('response', onResponse)
+ request.onUpgradeError(error)
+ }
+
+ const onReady = () => {
+ try {
request.onUpgrade(null, null, stream)
- ++session[kOpenStreams]
- client[kQueue][client[kRunningIdx]++] = null
- })
+ } catch (error) {
+ stream.off('response', onResponse)
+ abort(error)
+ return
+ }
+
+ if (request.aborted) {
+ return
+ }
+
+ stream.off('error', abort)
+ stream.once(errorMonitor, onUpgradeError)
+ client[kQueue][client[kRunningIdx]++] = null
}
+ stream.once('response', onResponse)
+ stream.once('error', abort)
+ ++session[kOpenStreams]
+ onReady()
+
stream.once('close', () => {
+ if (!upgradeResponseFinished && request.completed) {
+ stream.off('response', onResponse)
+ stream.off(errorMonitor, onUpgradeError)
+ request.onUpgradeError(new InformationalError(`HTTP/2: "stream error" received - code ${stream.rstCode}`))
+ }
session[kOpenStreams] -= 1
if (session[kOpenStreams] === 0) session.unref()
})