Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 3 additions & 22 deletions deps/undici/src/lib/core/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -431,22 +431,17 @@ function parseHeaders (headers, obj) {
val = [val]
obj[key] = val
}
val.push(headers[i + 1].toString('utf8'))
val.push(headers[i + 1].toString('latin1'))
} else {
const headersValue = headers[i + 1]
if (typeof headersValue === 'string') {
obj[key] = headersValue
} else {
obj[key] = Array.isArray(headersValue) ? headersValue.map(x => x.toString('utf8')) : headersValue.toString('utf8')
obj[key] = Array.isArray(headersValue) ? headersValue.map(x => x.toString('latin1')) : headersValue.toString('latin1')
}
}
}

// See https://github.com/nodejs/node/pull/46528
if ('content-length' in obj && 'content-disposition' in obj) {
obj['content-disposition'] = Buffer.from(obj['content-disposition']).toString('latin1')
}

return obj
}

Expand All @@ -461,34 +456,20 @@ function parseRawHeaders (headers) {
*/
const ret = new Array(headersLength)

let hasContentLength = false
let contentDispositionIdx = -1
let key
let val
let kLen = 0

for (let n = 0; n < headersLength; n += 2) {
key = headers[n]
val = headers[n + 1]

typeof key !== 'string' && (key = key.toString())
typeof val !== 'string' && (val = val.toString('utf8'))
typeof val !== 'string' && (val = val.toString('latin1'))

kLen = key.length
if (kLen === 14 && key[7] === '-' && (key === 'content-length' || key.toLowerCase() === 'content-length')) {
hasContentLength = true
} else if (kLen === 19 && key[7] === '-' && (key === 'content-disposition' || key.toLowerCase() === 'content-disposition')) {
contentDispositionIdx = n + 1
}
ret[n] = key
ret[n + 1] = val
}

// See https://github.com/nodejs/node/pull/46528
if (hasContentLength && contentDispositionIdx !== -1) {
ret[contentDispositionIdx] = Buffer.from(ret[contentDispositionIdx]).toString('latin1')
}

return ret
}

Expand Down
26 changes: 10 additions & 16 deletions deps/undici/src/lib/dispatcher/client-h2.js
Original file line number Diff line number Diff line change
Expand Up @@ -642,9 +642,13 @@ function writeH2 (client, request) {
++session[kOpenStreams]
stream.setTimeout(requestTimeout)

// Track whether we received a response (headers)
let responseReceived = false

stream.once('response', headers => {
const { [HTTP2_HEADER_STATUS]: statusCode, ...realHeaders } = headers
request.onResponseStarted()
responseReceived = true

// Due to the stream nature, it is possible we face a race condition
// where the stream has been assigned, but the request has been aborted
Expand All @@ -667,30 +671,20 @@ function writeH2 (client, request) {
}
})

stream.once('end', (err) => {
stream.once('end', () => {
stream.removeAllListeners('data')
// When state is null, it means we haven't consumed body and the stream still do not have
// a state.
// Present specially when using pipeline or stream
if (stream.state?.state == null || stream.state.state < 6) {
// Do not complete the request if it was aborted
// Not prone to happen for as safety net to avoid race conditions with 'trailers'
// If we received a response, this is a normal completion
if (responseReceived) {
if (!request.aborted && !request.completed) {
request.onComplete({})
}

client[kQueue][client[kRunningIdx]++] = null
client[kResume]()
} else {
// Stream is closed or half-closed-remote (6), decrement counter and cleanup
// It does not have sense to continue working with the stream as we do not
// have yet RST_STREAM support on client-side
--session[kOpenStreams]
if (session[kOpenStreams] === 0) {
session.unref()
}

abort(err ?? new InformationalError('HTTP/2: stream half-closed (remote)'))
// Stream ended without receiving a response - this is an error
// (e.g., server destroyed the stream before sending headers)
abort(new InformationalError('HTTP/2: stream half-closed (remote)'))
client[kQueue][client[kRunningIdx]++] = null
client[kPendingIdx] = client[kRunningIdx]
client[kResume]()
Expand Down
7 changes: 2 additions & 5 deletions deps/undici/src/lib/interceptor/decompress.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ let warningEmitted = /** @type {boolean} */ (false)
class DecompressHandler extends DecoratorHandler {
/** @type {Transform[]} */
#decompressors = []
/** @type {NodeJS.WritableStream&NodeJS.ReadableStream|null} */
#pipelineStream
/** @type {Readonly<number[]>} */
#skipStatusCodes
/** @type {boolean} */
Expand Down Expand Up @@ -139,7 +137,7 @@ class DecompressHandler extends DecoratorHandler {
const lastDecompressor = this.#decompressors[this.#decompressors.length - 1]
this.#setupDecompressorEvents(lastDecompressor, controller)

this.#pipelineStream = pipeline(this.#decompressors, (err) => {
pipeline(this.#decompressors, (err) => {
if (err) {
super.onResponseError(controller, err)
return
Expand All @@ -154,7 +152,6 @@ class DecompressHandler extends DecoratorHandler {
*/
#cleanupDecompressors () {
this.#decompressors.length = 0
this.#pipelineStream = null
}

/**
Expand Down Expand Up @@ -190,7 +187,7 @@ class DecompressHandler extends DecoratorHandler {
this.#setupMultipleDecompressors(controller)
}

super.onResponseStart(controller, statusCode, newHeaders, statusMessage)
return super.onResponseStart(controller, statusCode, newHeaders, statusMessage)
}

/**
Expand Down
2 changes: 1 addition & 1 deletion deps/undici/src/lib/llhttp/wasm_build_env.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

> undici@7.19.1 build:wasm
> undici@7.19.2 build:wasm
> node build/wasm.js --docker

> docker run --rm --platform=linux/x86_64 --user 1001:1001 --mount type=bind,source=/home/runner/work/node/node/deps/undici/src/lib/llhttp,target=/home/node/build/lib/llhttp --mount type=bind,source=/home/runner/work/node/node/deps/undici/src/build,target=/home/node/build/build --mount type=bind,source=/home/runner/work/node/node/deps/undici/src/deps,target=/home/node/build/deps -t ghcr.io/nodejs/wasm-builder@sha256:975f391d907e42a75b8c72eb77c782181e941608687d4d8694c3e9df415a0970 node build/wasm.js
Expand Down
4 changes: 2 additions & 2 deletions deps/undici/src/lib/web/fetch/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1677,9 +1677,9 @@ async function httpNetworkOrCacheFetch (
// requestCurrentURL(request).password = TODO

// In browsers, the user will be prompted to enter a username/password before the request
// is re-sent. To prevent an infinite 401 loop, return a network error for now.
// is re-sent. To prevent an infinite 401 loop, return the response for now.
// https://github.com/nodejs/undici/pull/4756
return makeNetworkError()
return response
}

// 4. Set response to the result of running HTTP-network-or-cache fetch given
Expand Down
Loading
Loading