Comparing version 5.22.0 to 5.21.2
@@ -6,6 +6,6 @@ 'use strict' | ||
InvalidArgumentError, | ||
RequestAbortedError | ||
RequestAbortedError, | ||
ResponseStatusCodeError | ||
} = 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, highWaterMark } = opts | ||
const { signal, method, opaque, body, onInfo, responseHeaders, throwOnError } = opts | ||
@@ -28,6 +28,2 @@ try { | ||
if (highWaterMark && (typeof highWaterMark !== 'number' || highWaterMark < 0)) { | ||
throw new InvalidArgumentError('invalid highWaterMark') | ||
} | ||
if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { | ||
@@ -63,3 +59,2 @@ throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') | ||
this.throwOnError = throwOnError | ||
this.highWaterMark = highWaterMark | ||
@@ -85,8 +80,7 @@ if (util.isStream(body)) { | ||
onHeaders (statusCode, rawHeaders, resume, statusMessage) { | ||
const { callback, opaque, abort, context, responseHeaders, highWaterMark } = this | ||
const { callback, opaque, abort, context } = 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 }) | ||
@@ -97,8 +91,9 @@ } | ||
const parsedHeaders = responseHeaders === 'raw' ? util.parseHeaders(rawHeaders) : headers | ||
const parsedHeaders = util.parseHeaders(rawHeaders) | ||
const contentType = parsedHeaders['content-type'] | ||
const body = new Readable({ resume, abort, contentType, highWaterMark }) | ||
const body = new Readable(resume, abort, contentType) | ||
this.callback = null | ||
this.res = body | ||
const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) | ||
@@ -110,12 +105,13 @@ if (callback !== null) { | ||
) | ||
} else { | ||
this.runInAsyncScope(callback, null, null, { | ||
statusCode, | ||
headers, | ||
trailers: this.trailers, | ||
opaque, | ||
body, | ||
context | ||
}) | ||
return | ||
} | ||
this.runInAsyncScope(callback, null, null, { | ||
statusCode, | ||
headers, | ||
trailers: this.trailers, | ||
opaque, | ||
body, | ||
context | ||
}) | ||
} | ||
@@ -167,2 +163,29 @@ } | ||
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) { | ||
@@ -169,0 +192,0 @@ if (callback === undefined) { |
@@ -7,6 +7,6 @@ 'use strict' | ||
InvalidReturnValueError, | ||
RequestAbortedError | ||
RequestAbortedError, | ||
ResponseStatusCodeError | ||
} = require('../core/errors') | ||
const util = require('../core/util') | ||
const { getResolveErrorBodyCallback } = require('./util') | ||
const { AsyncResource } = require('async_hooks') | ||
@@ -83,8 +83,7 @@ const { addSignal, removeSignal } = require('./abort-signal') | ||
onHeaders (statusCode, rawHeaders, resume, statusMessage) { | ||
const { factory, opaque, context, callback, responseHeaders } = this | ||
const { factory, opaque, context, callback } = 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 }) | ||
@@ -96,51 +95,63 @@ } | ||
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 parsedHeaders = responseHeaders === 'raw' ? util.parseHeaders(rawHeaders) : headers | ||
const contentType = parsedHeaders['content-type'] | ||
res = new PassThrough() | ||
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 | ||
} | ||
this.callback = null | ||
this.runInAsyncScope(getResolveErrorBodyCallback, null, | ||
{ callback, body: res, contentType, statusCode, statusMessage, headers } | ||
) | ||
} else { | ||
res = this.runInAsyncScope(factory, null, { | ||
statusCode, | ||
headers, | ||
opaque, | ||
context | ||
}) | ||
if ( | ||
!res || | ||
typeof res.write !== 'function' || | ||
typeof res.end !== 'function' || | ||
typeof res.on !== 'function' | ||
) { | ||
throw new InvalidReturnValueError('expected Writable') | ||
} | ||
if ( | ||
!res || | ||
typeof res.write !== 'function' || | ||
typeof res.end !== 'function' || | ||
typeof res.on !== 'function' | ||
) { | ||
throw new InvalidReturnValueError('expected Writable') | ||
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) | ||
} | ||
// TODO: Avoid finished. It registers an unnecessary amount of listeners. | ||
finished(res, { readable: false }, (err) => { | ||
const { callback, res, opaque, trailers, abort } = this | ||
this.callback = null | ||
this.runInAsyncScope(callback, null, err || null, { opaque, trailers }) | ||
this.res = null | ||
if (err || !res.readable) { | ||
util.destroy(res, err) | ||
} | ||
if (err) { | ||
abort() | ||
} | ||
}) | ||
this.callback = null | ||
this.runInAsyncScope(callback, null, err || null, { opaque, trailers }) | ||
if (err) { | ||
abort() | ||
} | ||
}) | ||
} | ||
res.on('drain', resume) | ||
this.res = res | ||
@@ -147,0 +158,0 @@ |
@@ -20,12 +20,7 @@ // Ported from https://github.com/nodejs/undici/pull/907 | ||
module.exports = class BodyReadable extends Readable { | ||
constructor ({ | ||
resume, | ||
abort, | ||
contentType = '', | ||
highWaterMark = 64 * 1024 // Same as nodejs fs streams. | ||
}) { | ||
constructor (resume, abort, contentType = '') { | ||
super({ | ||
autoDestroy: true, | ||
read: resume, | ||
highWaterMark | ||
highWaterMark: 64 * 1024 // Same as nodejs fs streams. | ||
}) | ||
@@ -32,0 +27,0 @@ |
@@ -24,4 +24,3 @@ // @ts-check | ||
HTTPParserError, | ||
ResponseExceededMaxSizeError, | ||
ClientDestroyedError | ||
ResponseExceededMaxSizeError | ||
} = require('./core/errors') | ||
@@ -325,3 +324,3 @@ const buildConnector = require('./core/connect') | ||
if (!this[kSize]) { | ||
resolve(null) | ||
this.destroy(resolve) | ||
} else { | ||
@@ -343,3 +342,2 @@ this[kClosedResolve] = resolve | ||
if (this[kClosedResolve]) { | ||
// TODO (fix): Should we error here with ClientDestroyedError? | ||
this[kClosedResolve]() | ||
@@ -367,7 +365,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) { | ||
@@ -380,3 +378,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')) | ||
} | ||
@@ -1092,7 +1090,2 @@ | ||
if (client.destroyed) { | ||
util.destroy(socket.on('error', () => {}), new ClientDestroyedError()) | ||
return | ||
} | ||
if (!llhttpInstance) { | ||
@@ -1140,6 +1133,2 @@ llhttpInstance = await llhttpPromise | ||
} catch (err) { | ||
if (client.destroyed) { | ||
return | ||
} | ||
client[kConnecting] = false | ||
@@ -1207,5 +1196,4 @@ | ||
if (client[kClosedResolve] && !client[kSize]) { | ||
client[kClosedResolve]() | ||
client[kClosedResolve] = null | ||
if (client.closed && !client[kSize]) { | ||
client.destroy() | ||
return | ||
@@ -1462,6 +1450,6 @@ } | ||
if (contentLength === 0) { | ||
socket.write(`${header}content-length: 0\r\n\r\n`, 'latin1') | ||
socket.write(`${header}content-length: 0\r\n\r\n`, 'ascii') | ||
} else { | ||
assert(contentLength === null, 'no body must not have content length') | ||
socket.write(`${header}\r\n`, 'latin1') | ||
socket.write(`${header}\r\n`, 'ascii') | ||
} | ||
@@ -1473,3 +1461,3 @@ request.onRequestSent() | ||
socket.cork() | ||
socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'latin1') | ||
socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'ascii') | ||
socket.write(body) | ||
@@ -1589,3 +1577,3 @@ socket.uncork() | ||
socket.cork() | ||
socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'latin1') | ||
socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'ascii') | ||
socket.write(buffer) | ||
@@ -1702,5 +1690,5 @@ socket.uncork() | ||
if (contentLength === null) { | ||
socket.write(`${header}transfer-encoding: chunked\r\n`, 'latin1') | ||
socket.write(`${header}transfer-encoding: chunked\r\n`, 'ascii') | ||
} else { | ||
socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'latin1') | ||
socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'ascii') | ||
} | ||
@@ -1710,3 +1698,3 @@ } | ||
if (contentLength === null) { | ||
socket.write(`\r\n${len.toString(16)}\r\n`, 'latin1') | ||
socket.write(`\r\n${len.toString(16)}\r\n`, 'ascii') | ||
} | ||
@@ -1755,8 +1743,8 @@ | ||
socket.write(`${header}content-length: 0\r\n\r\n`, 'latin1') | ||
socket.write(`${header}content-length: 0\r\n\r\n`, 'ascii') | ||
} else { | ||
socket.write(`${header}\r\n`, 'latin1') | ||
socket.write(`${header}\r\n`, 'ascii') | ||
} | ||
} else if (contentLength === null) { | ||
socket.write('\r\n0\r\n\r\n', 'latin1') | ||
socket.write('\r\n0\r\n\r\n', 'ascii') | ||
} | ||
@@ -1763,0 +1751,0 @@ |
@@ -185,3 +185,2 @@ 'use strict' | ||
this.body = bodyStream.stream | ||
this.contentLength = bodyStream.length | ||
} else if (util.isBlobLike(body) && this.contentType == null && body.type) { | ||
@@ -188,0 +187,0 @@ this.contentType = body.type |
@@ -22,3 +22,3 @@ 'use strict' | ||
this[kDestroyed] = false | ||
this[kOnDestroyed] = null | ||
this[kOnDestroyed] = [] | ||
this[kClosed] = false | ||
@@ -131,3 +131,2 @@ this[kOnClosed] = [] | ||
this[kDestroyed] = true | ||
this[kOnDestroyed] = this[kOnDestroyed] || [] | ||
this[kOnDestroyed].push(callback) | ||
@@ -173,3 +172,3 @@ | ||
if (this[kDestroyed] || this[kOnDestroyed]) { | ||
if (this[kDestroyed]) { | ||
throw new ClientDestroyedError() | ||
@@ -176,0 +175,0 @@ } |
@@ -6,3 +6,3 @@ // https://github.com/Ethan-Arrowood/undici-fetch | ||
const { kHeadersList } = require('../core/symbols') | ||
const { kGuard } = require('./symbols') | ||
const { kGuard, kHeadersCaseInsensitive } = require('./symbols') | ||
const { kEnumerableProperty } = require('../core/util') | ||
@@ -177,12 +177,11 @@ const { | ||
get entries () { | ||
const headers = {} | ||
get [kHeadersCaseInsensitive] () { | ||
/** @type {string[]} */ | ||
const flatList = [] | ||
if (this[kHeadersMap].size) { | ||
for (const { name, value } of this[kHeadersMap].values()) { | ||
headers[name] = value | ||
} | ||
for (const { name, value } of this[kHeadersMap].values()) { | ||
flatList.push(name, value) | ||
} | ||
return headers | ||
return flatList | ||
} | ||
@@ -522,3 +521,2 @@ } | ||
set: kEnumerableProperty, | ||
getSetCookie: kEnumerableProperty, | ||
keys: kEnumerableProperty, | ||
@@ -525,0 +523,0 @@ values: kEnumerableProperty, |
@@ -32,3 +32,3 @@ /* globals AbortController */ | ||
const assert = require('assert') | ||
const { getMaxListeners, setMaxListeners, getEventListeners, defaultMaxListeners } = require('events') | ||
const { setMaxListeners, getEventListeners, defaultMaxListeners } = require('events') | ||
@@ -376,8 +376,4 @@ let TransformStream = globalThis.TransformStream | ||
try { | ||
// 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) { | ||
if (getEventListeners(signal, 'abort').length >= defaultMaxListeners) { | ||
setMaxListeners(100, signal) | ||
} else if (getEventListeners(signal, 'abort').length >= defaultMaxListeners) { | ||
setMaxListeners(100, signal) | ||
} | ||
@@ -384,0 +380,0 @@ } catch {} |
@@ -9,3 +9,4 @@ 'use strict' | ||
kGuard: Symbol('guard'), | ||
kRealm: Symbol('realm') | ||
kRealm: Symbol('realm'), | ||
kHeadersCaseInsensitive: Symbol('headers case insensitive') | ||
} |
@@ -641,5 +641,3 @@ 'use strict' | ||
// 1. If A and B are the same opaque origin, then return true. | ||
if (A.origin === B.origin && A.origin === 'null') { | ||
return true | ||
} | ||
// "opaque origin" is an internal value we cannot access, ignore. | ||
@@ -646,0 +644,0 @@ // 2. If A and B are both tuple origins and their schemes, |
{ | ||
"name": "undici", | ||
"version": "5.22.0", | ||
"version": "5.21.2", | ||
"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 && npm run test:typescript", | ||
"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: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": "node scripts/verifyVersion.js 14 || tsd && tsc --skipLibCheck test/imports/undici-import.ts", | ||
"test:typescript": "tsd && tsc 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.28.1", | ||
"tsd": "^0.27.0", | ||
"typescript": "^5.0.2", | ||
@@ -110,3 +110,3 @@ "wait-on": "^7.0.1", | ||
"engines": { | ||
"node": ">=14.0" | ||
"node": ">=12.18" | ||
}, | ||
@@ -113,0 +113,0 @@ "standard": { |
@@ -30,5 +30,11 @@ import { TLSSocket, ConnectionOptions } from 'tls' | ||
export interface connector { | ||
export type connector = connectorAsync | connectorSync | ||
interface connectorSync { | ||
(options: buildConnector.Options): Socket | TLSSocket | ||
} | ||
interface connectorAsync { | ||
(options: buildConnector.Options, callback: buildConnector.Callback): void | ||
} | ||
} |
@@ -145,4 +145,2 @@ import { URL } from 'url' | ||
responseHeader?: 'raw' | null; | ||
/** Default: `64 KiB` */ | ||
highWaterMark?: number; | ||
} | ||
@@ -149,0 +147,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
1087787
141
18335