Comparing version 5.21.2 to 5.22.0
@@ -6,6 +6,6 @@ 'use strict' | ||
InvalidArgumentError, | ||
RequestAbortedError, | ||
ResponseStatusCodeError | ||
RequestAbortedError | ||
} = require('../core/errors') | ||
const util = require('../core/util') | ||
const { getResolveErrorBodyCallback } = require('./util') | ||
const { AsyncResource } = require('async_hooks') | ||
@@ -20,3 +20,3 @@ const { addSignal, removeSignal } = require('./abort-signal') | ||
const { signal, method, opaque, body, onInfo, responseHeaders, throwOnError } = opts | ||
const { signal, method, opaque, body, onInfo, responseHeaders, throwOnError, highWaterMark } = opts | ||
@@ -28,2 +28,6 @@ try { | ||
if (highWaterMark && (typeof highWaterMark !== 'number' || highWaterMark < 0)) { | ||
throw new InvalidArgumentError('invalid highWaterMark') | ||
} | ||
if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { | ||
@@ -59,2 +63,3 @@ throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') | ||
this.throwOnError = throwOnError | ||
this.highWaterMark = highWaterMark | ||
@@ -80,7 +85,8 @@ if (util.isStream(body)) { | ||
onHeaders (statusCode, rawHeaders, resume, statusMessage) { | ||
const { callback, opaque, abort, context } = this | ||
const { callback, opaque, abort, context, responseHeaders, highWaterMark } = this | ||
const headers = responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) | ||
if (statusCode < 200) { | ||
if (this.onInfo) { | ||
const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) | ||
this.onInfo({ statusCode, headers }) | ||
@@ -91,9 +97,8 @@ } | ||
const parsedHeaders = util.parseHeaders(rawHeaders) | ||
const parsedHeaders = responseHeaders === 'raw' ? util.parseHeaders(rawHeaders) : headers | ||
const contentType = parsedHeaders['content-type'] | ||
const body = new Readable(resume, abort, contentType) | ||
const body = new Readable({ resume, abort, contentType, highWaterMark }) | ||
this.callback = null | ||
this.res = body | ||
const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) | ||
@@ -105,13 +110,12 @@ if (callback !== null) { | ||
) | ||
return | ||
} else { | ||
this.runInAsyncScope(callback, null, null, { | ||
statusCode, | ||
headers, | ||
trailers: this.trailers, | ||
opaque, | ||
body, | ||
context | ||
}) | ||
} | ||
this.runInAsyncScope(callback, null, null, { | ||
statusCode, | ||
headers, | ||
trailers: this.trailers, | ||
opaque, | ||
body, | ||
context | ||
}) | ||
} | ||
@@ -163,29 +167,2 @@ } | ||
async function getResolveErrorBodyCallback ({ callback, body, contentType, statusCode, statusMessage, headers }) { | ||
if (statusCode === 204 || !contentType) { | ||
body.dump() | ||
process.nextTick(callback, new ResponseStatusCodeError(`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`, statusCode, headers)) | ||
return | ||
} | ||
try { | ||
if (contentType.startsWith('application/json')) { | ||
const payload = await body.json() | ||
process.nextTick(callback, new ResponseStatusCodeError(`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`, statusCode, headers, payload)) | ||
return | ||
} | ||
if (contentType.startsWith('text/')) { | ||
const payload = await body.text() | ||
process.nextTick(callback, new ResponseStatusCodeError(`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`, statusCode, headers, payload)) | ||
return | ||
} | ||
} catch (err) { | ||
// Process in a fallback if error | ||
} | ||
body.dump() | ||
process.nextTick(callback, new ResponseStatusCodeError(`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`, statusCode, headers)) | ||
} | ||
function request (opts, callback) { | ||
@@ -192,0 +169,0 @@ if (callback === undefined) { |
@@ -7,6 +7,6 @@ 'use strict' | ||
InvalidReturnValueError, | ||
RequestAbortedError, | ||
ResponseStatusCodeError | ||
RequestAbortedError | ||
} = require('../core/errors') | ||
const util = require('../core/util') | ||
const { getResolveErrorBodyCallback } = require('./util') | ||
const { AsyncResource } = require('async_hooks') | ||
@@ -83,7 +83,8 @@ const { addSignal, removeSignal } = require('./abort-signal') | ||
onHeaders (statusCode, rawHeaders, resume, statusMessage) { | ||
const { factory, opaque, context, callback } = this | ||
const { factory, opaque, context, callback, responseHeaders } = this | ||
const headers = responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) | ||
if (statusCode < 200) { | ||
if (this.onInfo) { | ||
const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) | ||
this.onInfo({ statusCode, headers }) | ||
@@ -95,63 +96,51 @@ } | ||
this.factory = null | ||
const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) | ||
const res = this.runInAsyncScope(factory, null, { | ||
statusCode, | ||
headers, | ||
opaque, | ||
context | ||
}) | ||
let res | ||
if (this.throwOnError && statusCode >= 400) { | ||
const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) | ||
const chunks = [] | ||
const pt = new PassThrough() | ||
pt | ||
.on('data', (chunk) => chunks.push(chunk)) | ||
.on('end', () => { | ||
const payload = Buffer.concat(chunks).toString('utf8') | ||
this.runInAsyncScope( | ||
callback, | ||
null, | ||
new ResponseStatusCodeError( | ||
`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`, | ||
statusCode, | ||
headers, | ||
payload | ||
) | ||
) | ||
}) | ||
.on('error', (err) => { | ||
this.onError(err) | ||
}) | ||
this.res = pt | ||
return | ||
} | ||
const parsedHeaders = responseHeaders === 'raw' ? util.parseHeaders(rawHeaders) : headers | ||
const contentType = parsedHeaders['content-type'] | ||
res = new PassThrough() | ||
if ( | ||
!res || | ||
typeof res.write !== 'function' || | ||
typeof res.end !== 'function' || | ||
typeof res.on !== 'function' | ||
) { | ||
throw new InvalidReturnValueError('expected Writable') | ||
} | ||
this.callback = null | ||
this.runInAsyncScope(getResolveErrorBodyCallback, null, | ||
{ callback, body: res, contentType, statusCode, statusMessage, headers } | ||
) | ||
} else { | ||
res = this.runInAsyncScope(factory, null, { | ||
statusCode, | ||
headers, | ||
opaque, | ||
context | ||
}) | ||
res.on('drain', resume) | ||
// TODO: Avoid finished. It registers an unnecessary amount of listeners. | ||
finished(res, { readable: false }, (err) => { | ||
const { callback, res, opaque, trailers, abort } = this | ||
this.res = null | ||
if (err || !res.readable) { | ||
util.destroy(res, err) | ||
if ( | ||
!res || | ||
typeof res.write !== 'function' || | ||
typeof res.end !== 'function' || | ||
typeof res.on !== 'function' | ||
) { | ||
throw new InvalidReturnValueError('expected Writable') | ||
} | ||
this.callback = null | ||
this.runInAsyncScope(callback, null, err || null, { opaque, trailers }) | ||
// TODO: Avoid finished. It registers an unnecessary amount of listeners. | ||
finished(res, { readable: false }, (err) => { | ||
const { callback, res, opaque, trailers, abort } = this | ||
if (err) { | ||
abort() | ||
} | ||
}) | ||
this.res = null | ||
if (err || !res.readable) { | ||
util.destroy(res, err) | ||
} | ||
this.callback = null | ||
this.runInAsyncScope(callback, null, err || null, { opaque, trailers }) | ||
if (err) { | ||
abort() | ||
} | ||
}) | ||
} | ||
res.on('drain', resume) | ||
this.res = res | ||
@@ -158,0 +147,0 @@ |
@@ -20,7 +20,12 @@ // Ported from https://github.com/nodejs/undici/pull/907 | ||
module.exports = class BodyReadable extends Readable { | ||
constructor (resume, abort, contentType = '') { | ||
constructor ({ | ||
resume, | ||
abort, | ||
contentType = '', | ||
highWaterMark = 64 * 1024 // Same as nodejs fs streams. | ||
}) { | ||
super({ | ||
autoDestroy: true, | ||
read: resume, | ||
highWaterMark: 64 * 1024 // Same as nodejs fs streams. | ||
highWaterMark | ||
}) | ||
@@ -27,0 +32,0 @@ |
@@ -24,3 +24,4 @@ // @ts-check | ||
HTTPParserError, | ||
ResponseExceededMaxSizeError | ||
ResponseExceededMaxSizeError, | ||
ClientDestroyedError | ||
} = require('./core/errors') | ||
@@ -324,3 +325,3 @@ const buildConnector = require('./core/connect') | ||
if (!this[kSize]) { | ||
this.destroy(resolve) | ||
resolve(null) | ||
} else { | ||
@@ -342,2 +343,3 @@ this[kClosedResolve] = resolve | ||
if (this[kClosedResolve]) { | ||
// TODO (fix): Should we error here with ClientDestroyedError? | ||
this[kClosedResolve]() | ||
@@ -365,7 +367,7 @@ this[kClosedResolve] = null | ||
async function lazyllhttp () { | ||
const llhttpWasmData = process.env.JEST_WORKER_ID ? require('./llhttp/llhttp.wasm.js') : undefined | ||
const llhttpWasmData = process.env.JEST_WORKER_ID ? require('./llhttp/llhttp-wasm.js') : undefined | ||
let mod | ||
try { | ||
mod = await WebAssembly.compile(Buffer.from(require('./llhttp/llhttp_simd.wasm.js'), 'base64')) | ||
mod = await WebAssembly.compile(Buffer.from(require('./llhttp/llhttp_simd-wasm.js'), 'base64')) | ||
} catch (e) { | ||
@@ -378,3 +380,3 @@ /* istanbul ignore next */ | ||
// got me to remove that check to avoid breaking Node 12. | ||
mod = await WebAssembly.compile(Buffer.from(llhttpWasmData || require('./llhttp/llhttp.wasm.js'), 'base64')) | ||
mod = await WebAssembly.compile(Buffer.from(llhttpWasmData || require('./llhttp/llhttp-wasm.js'), 'base64')) | ||
} | ||
@@ -1090,2 +1092,7 @@ | ||
if (client.destroyed) { | ||
util.destroy(socket.on('error', () => {}), new ClientDestroyedError()) | ||
return | ||
} | ||
if (!llhttpInstance) { | ||
@@ -1133,2 +1140,6 @@ llhttpInstance = await llhttpPromise | ||
} catch (err) { | ||
if (client.destroyed) { | ||
return | ||
} | ||
client[kConnecting] = false | ||
@@ -1196,4 +1207,5 @@ | ||
if (client.closed && !client[kSize]) { | ||
client.destroy() | ||
if (client[kClosedResolve] && !client[kSize]) { | ||
client[kClosedResolve]() | ||
client[kClosedResolve] = null | ||
return | ||
@@ -1450,6 +1462,6 @@ } | ||
if (contentLength === 0) { | ||
socket.write(`${header}content-length: 0\r\n\r\n`, 'ascii') | ||
socket.write(`${header}content-length: 0\r\n\r\n`, 'latin1') | ||
} else { | ||
assert(contentLength === null, 'no body must not have content length') | ||
socket.write(`${header}\r\n`, 'ascii') | ||
socket.write(`${header}\r\n`, 'latin1') | ||
} | ||
@@ -1461,3 +1473,3 @@ request.onRequestSent() | ||
socket.cork() | ||
socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'ascii') | ||
socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'latin1') | ||
socket.write(body) | ||
@@ -1577,3 +1589,3 @@ socket.uncork() | ||
socket.cork() | ||
socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'ascii') | ||
socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'latin1') | ||
socket.write(buffer) | ||
@@ -1690,5 +1702,5 @@ socket.uncork() | ||
if (contentLength === null) { | ||
socket.write(`${header}transfer-encoding: chunked\r\n`, 'ascii') | ||
socket.write(`${header}transfer-encoding: chunked\r\n`, 'latin1') | ||
} else { | ||
socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'ascii') | ||
socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'latin1') | ||
} | ||
@@ -1698,3 +1710,3 @@ } | ||
if (contentLength === null) { | ||
socket.write(`\r\n${len.toString(16)}\r\n`, 'ascii') | ||
socket.write(`\r\n${len.toString(16)}\r\n`, 'latin1') | ||
} | ||
@@ -1743,8 +1755,8 @@ | ||
socket.write(`${header}content-length: 0\r\n\r\n`, 'ascii') | ||
socket.write(`${header}content-length: 0\r\n\r\n`, 'latin1') | ||
} else { | ||
socket.write(`${header}\r\n`, 'ascii') | ||
socket.write(`${header}\r\n`, 'latin1') | ||
} | ||
} else if (contentLength === null) { | ||
socket.write('\r\n0\r\n\r\n', 'ascii') | ||
socket.write('\r\n0\r\n\r\n', 'latin1') | ||
} | ||
@@ -1751,0 +1763,0 @@ |
@@ -185,2 +185,3 @@ 'use strict' | ||
this.body = bodyStream.stream | ||
this.contentLength = bodyStream.length | ||
} else if (util.isBlobLike(body) && this.contentType == null && body.type) { | ||
@@ -187,0 +188,0 @@ this.contentType = body.type |
@@ -22,3 +22,3 @@ 'use strict' | ||
this[kDestroyed] = false | ||
this[kOnDestroyed] = [] | ||
this[kOnDestroyed] = null | ||
this[kClosed] = false | ||
@@ -131,2 +131,3 @@ this[kOnClosed] = [] | ||
this[kDestroyed] = true | ||
this[kOnDestroyed] = this[kOnDestroyed] || [] | ||
this[kOnDestroyed].push(callback) | ||
@@ -172,3 +173,3 @@ | ||
if (this[kDestroyed]) { | ||
if (this[kDestroyed] || this[kOnDestroyed]) { | ||
throw new ClientDestroyedError() | ||
@@ -175,0 +176,0 @@ } |
@@ -6,3 +6,3 @@ // https://github.com/Ethan-Arrowood/undici-fetch | ||
const { kHeadersList } = require('../core/symbols') | ||
const { kGuard, kHeadersCaseInsensitive } = require('./symbols') | ||
const { kGuard } = require('./symbols') | ||
const { kEnumerableProperty } = require('../core/util') | ||
@@ -177,11 +177,12 @@ const { | ||
get [kHeadersCaseInsensitive] () { | ||
/** @type {string[]} */ | ||
const flatList = [] | ||
get entries () { | ||
const headers = {} | ||
for (const { name, value } of this[kHeadersMap].values()) { | ||
flatList.push(name, value) | ||
if (this[kHeadersMap].size) { | ||
for (const { name, value } of this[kHeadersMap].values()) { | ||
headers[name] = value | ||
} | ||
} | ||
return flatList | ||
return headers | ||
} | ||
@@ -521,2 +522,3 @@ } | ||
set: kEnumerableProperty, | ||
getSetCookie: kEnumerableProperty, | ||
keys: kEnumerableProperty, | ||
@@ -523,0 +525,0 @@ values: kEnumerableProperty, |
@@ -32,3 +32,3 @@ /* globals AbortController */ | ||
const assert = require('assert') | ||
const { setMaxListeners, getEventListeners, defaultMaxListeners } = require('events') | ||
const { getMaxListeners, setMaxListeners, getEventListeners, defaultMaxListeners } = require('events') | ||
@@ -376,4 +376,8 @@ let TransformStream = globalThis.TransformStream | ||
try { | ||
if (getEventListeners(signal, 'abort').length >= defaultMaxListeners) { | ||
// If the max amount of listeners is equal to the default, increase it | ||
// This is only available in node >= v19.9.0 | ||
if (typeof getMaxListeners === 'function' && getMaxListeners(signal) === defaultMaxListeners) { | ||
setMaxListeners(100, signal) | ||
} else if (getEventListeners(signal, 'abort').length >= defaultMaxListeners) { | ||
setMaxListeners(100, signal) | ||
} | ||
@@ -380,0 +384,0 @@ } catch {} |
@@ -9,4 +9,3 @@ 'use strict' | ||
kGuard: Symbol('guard'), | ||
kRealm: Symbol('realm'), | ||
kHeadersCaseInsensitive: Symbol('headers case insensitive') | ||
kRealm: Symbol('realm') | ||
} |
@@ -641,3 +641,5 @@ 'use strict' | ||
// 1. If A and B are the same opaque origin, then return true. | ||
// "opaque origin" is an internal value we cannot access, ignore. | ||
if (A.origin === B.origin && A.origin === 'null') { | ||
return true | ||
} | ||
@@ -644,0 +646,0 @@ // 2. If A and B are both tuple origins and their schemes, |
{ | ||
"name": "undici", | ||
"version": "5.21.2", | ||
"version": "5.22.0", | ||
"description": "An HTTP/1.1 client, written from scratch for Node.js", | ||
@@ -49,3 +49,3 @@ "homepage": "https://undici.nodejs.org", | ||
"lint:fix": "standard --fix | snazzy", | ||
"test": "npm run test:tap && npm run test:node-fetch && npm run test:fetch && npm run test:cookies && npm run test:wpt && npm run test:websocket && npm run test:jest && tsd", | ||
"test": "npm run test:tap && npm run test:node-fetch && npm run test:fetch && npm run test:cookies && npm run test:wpt && npm run test:websocket && npm run test:jest && npm run test:typescript", | ||
"test:cookies": "node scripts/verifyVersion 16 || tap test/cookie/*.js", | ||
@@ -57,3 +57,3 @@ "test:node-fetch": "node scripts/verifyVersion.js 16 || mocha test/node-fetch", | ||
"test:tdd": "tap test/*.js test/diagnostics-channel/*.js -w", | ||
"test:typescript": "tsd && tsc test/imports/undici-import.ts", | ||
"test:typescript": "node scripts/verifyVersion.js 14 || tsd && tsc --skipLibCheck test/imports/undici-import.ts", | ||
"test:websocket": "node scripts/verifyVersion.js 18 || tap test/websocket/*.js", | ||
@@ -103,3 +103,3 @@ "test:wpt": "node scripts/verifyVersion 18 || (node test/wpt/start-fetch.mjs && node test/wpt/start-FileAPI.mjs && node test/wpt/start-mimesniff.mjs && node test/wpt/start-xhr.mjs && node --no-warnings test/wpt/start-websockets.mjs)", | ||
"tap": "^16.1.0", | ||
"tsd": "^0.27.0", | ||
"tsd": "^0.28.1", | ||
"typescript": "^5.0.2", | ||
@@ -110,3 +110,3 @@ "wait-on": "^7.0.1", | ||
"engines": { | ||
"node": ">=12.18" | ||
"node": ">=14.0" | ||
}, | ||
@@ -113,0 +113,0 @@ "standard": { |
@@ -30,11 +30,5 @@ import { TLSSocket, ConnectionOptions } from 'tls' | ||
export type connector = connectorAsync | connectorSync | ||
interface connectorSync { | ||
(options: buildConnector.Options): Socket | TLSSocket | ||
} | ||
interface connectorAsync { | ||
export interface connector { | ||
(options: buildConnector.Options, callback: buildConnector.Callback): void | ||
} | ||
} |
@@ -145,2 +145,4 @@ import { URL } from 'url' | ||
responseHeader?: 'raw' | null; | ||
/** Default: `64 KiB` */ | ||
highWaterMark?: number; | ||
} | ||
@@ -147,0 +149,0 @@ export interface PipelineOptions extends RequestOptions { |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1088722
142
18360