Socket
Socket
Sign inDemoInstall

undici

Package Overview
Dependencies
Maintainers
3
Versions
212
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

undici - npm Package Compare versions

Comparing version 6.7.1 to 6.8.0

1

docs/docs/api/Errors.md

@@ -29,2 +29,3 @@ # Errors

| `ResponseExceededMaxSizeError` | `UND_ERR_RES_EXCEEDED_MAX_SIZE` | response body exceed the max size allowed |
| `SecureProxyConnectionError` | `UND_ERR_PRX_TLS` | tls connection to a proxy failed |

@@ -31,0 +32,0 @@ ### `SocketError`

3

lib/api/api-request.js

@@ -94,3 +94,4 @@ 'use strict'

const contentType = parsedHeaders['content-type']
const body = new Readable({ resume, abort, contentType, highWaterMark })
const contentLength = parsedHeaders['content-length']
const body = new Readable({ resume, abort, contentType, contentLength, highWaterMark })

@@ -97,0 +98,0 @@ this.callback = null

@@ -14,4 +14,5 @@ // Ported from https://github.com/nodejs/undici/pull/907

const kBody = Symbol('kBody')
const kAbort = Symbol('abort')
const kAbort = Symbol('kAbort')
const kContentType = Symbol('kContentType')
const kContentLength = Symbol('kContentLength')

@@ -25,2 +26,3 @@ const noop = () => {}

contentType = '',
contentLength,
highWaterMark = 64 * 1024 // Same as nodejs fs streams.

@@ -40,2 +42,3 @@ }) {

this[kContentType] = contentType
this[kContentLength] = contentLength

@@ -152,3 +155,3 @@ // Is stream being consumed through Readable API?

async dump (opts) {
let limit = Number.isFinite(opts?.limit) ? opts.limit : 262144
let limit = Number.isFinite(opts?.limit) ? opts.limit : 128 * 1024
const signal = opts?.signal

@@ -167,2 +170,6 @@

return await new Promise((resolve, reject) => {
if (this[kContentLength] > limit) {
this.destroy(new AbortError())
}
const onAbort = () => {

@@ -169,0 +176,0 @@ this.destroy(signal.reason ?? new AbortError())

@@ -24,26 +24,64 @@ const assert = require('node:assert')

const message = `Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`
if (statusCode === 204 || !contentType || !chunks) {
process.nextTick(callback, new ResponseStatusCodeError(`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`, statusCode, headers))
queueMicrotask(() => callback(new ResponseStatusCodeError(message, statusCode, headers)))
return
}
const stackTraceLimit = Error.stackTraceLimit
Error.stackTraceLimit = 0
let payload
try {
if (contentType.startsWith('application/json')) {
const payload = JSON.parse(chunksDecode(chunks, length))
process.nextTick(callback, new ResponseStatusCodeError(`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`, statusCode, headers, payload))
return
if (isContentTypeApplicationJson(contentType)) {
payload = JSON.parse(chunksDecode(chunks, length))
} else if (isContentTypeText(contentType)) {
payload = chunksDecode(chunks, length)
}
if (contentType.startsWith('text/')) {
const payload = chunksDecode(chunks, length)
process.nextTick(callback, new ResponseStatusCodeError(`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`, statusCode, headers, payload))
return
}
} catch (err) {
// Process in a fallback if error
} catch {
// process in a callback to avoid throwing in the microtask queue
} finally {
Error.stackTraceLimit = stackTraceLimit
}
queueMicrotask(() => callback(new ResponseStatusCodeError(message, statusCode, headers, payload)))
}
process.nextTick(callback, new ResponseStatusCodeError(`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`, statusCode, headers))
const isContentTypeApplicationJson = (contentType) => {
return (
contentType.length > 15 &&
contentType[11] === '/' &&
contentType[0] === 'a' &&
contentType[1] === 'p' &&
contentType[2] === 'p' &&
contentType[3] === 'l' &&
contentType[4] === 'i' &&
contentType[5] === 'c' &&
contentType[6] === 'a' &&
contentType[7] === 't' &&
contentType[8] === 'i' &&
contentType[9] === 'o' &&
contentType[10] === 'n' &&
contentType[12] === 'j' &&
contentType[13] === 's' &&
contentType[14] === 'o' &&
contentType[15] === 'n'
)
}
module.exports = { getResolveErrorBodyCallback }
const isContentTypeText = (contentType) => {
return (
contentType.length > 4 &&
contentType[4] === '/' &&
contentType[0] === 't' &&
contentType[1] === 'e' &&
contentType[2] === 'x' &&
contentType[3] === 't'
)
}
module.exports = {
getResolveErrorBodyCallback,
isContentTypeApplicationJson,
isContentTypeText
}

@@ -198,2 +198,12 @@ 'use strict'

class SecureProxyConnectionError extends UndiciError {
constructor (cause, message, options) {
super(message, { cause, ...(options ?? {}) })
this.name = 'SecureProxyConnectionError'
this.message = message || 'Secure Proxy Connection failed'
this.code = 'UND_ERR_PRX_TLS'
this.cause = cause
}
}
module.exports = {

@@ -220,3 +230,4 @@ AbortError,

ResponseExceededMaxSizeError,
RequestRetryError
RequestRetryError,
SecureProxyConnectionError
}

@@ -43,3 +43,4 @@ 'use strict'

throwOnError,
expectContinue
expectContinue,
servername
}, handler) {

@@ -185,3 +186,3 @@ if (typeof path !== 'string') {

this.servername = getServerName(this.host)
this.servername = servername || getServerName(this.host)

@@ -188,0 +189,0 @@ this[kHandler] = handler

@@ -443,3 +443,4 @@ 'use strict'

const hasToWellFormed = !!String.prototype.toWellFormed
const hasToWellFormed = typeof String.prototype.toWellFormed === 'function'
const hasIsWellFormed = typeof String.prototype.isWellFormed === 'function'

@@ -454,2 +455,10 @@ /**

/**
* @param {string} val
*/
// TODO: move this to webidl
function isUSVString (val) {
return hasIsWellFormed ? `${val}`.isWellFormed() : toUSVString(val) === `${val}`
}
/**
* @see https://tools.ietf.org/html/rfc7230#section-3.2.6

@@ -543,2 +552,3 @@ * @param {number} c

toUSVString,
isUSVString,
isReadableAborted,

@@ -545,0 +555,0 @@ isBlobLike,

@@ -8,3 +8,3 @@ 'use strict'

const DispatcherBase = require('./dispatcher-base')
const { InvalidArgumentError, RequestAbortedError } = require('../core/errors')
const { InvalidArgumentError, RequestAbortedError, SecureProxyConnectionError } = require('../core/errors')
const buildConnector = require('../core/connect')

@@ -41,6 +41,5 @@

const url = this.#getUrl(opts)
const { href, origin, port, protocol, username, password } = url
const { href, origin, port, protocol, username, password, hostname: proxyHostname } = url
this[kProxy] = { uri: href, protocol }
this[kAgent] = new Agent(opts)
this[kInterceptors] = opts.interceptors?.ProxyAgent && Array.isArray(opts.interceptors.ProxyAgent)

@@ -83,3 +82,4 @@ ? opts.interceptors.ProxyAgent

host: requestedHost
}
},
servername: this[kProxyTls]?.servername || proxyHostname
})

@@ -102,3 +102,8 @@ if (statusCode !== 200) {

} catch (err) {
callback(err)
if (err.code === 'ERR_TLS_CERT_ALTNAME_INVALID') {
// Throw a custom error to avoid loop in client.js#connect
callback(new SecureProxyConnectionError(err))
} else {
callback(err)
}
}

@@ -105,0 +110,0 @@ }

'use strict'
const { webidl } = require('./webidl')
const { toUSVString, isUSVString, bufferToLowerCasedHeaderName } = require('../../core/util')
const { utf8DecodeBytes } = require('./util')

@@ -9,3 +9,3 @@ const { HTTP_TOKEN_CODEPOINTS, isomorphicDecode } = require('./data-url')

const assert = require('node:assert')
const { isAscii, File: NodeFile } = require('node:buffer')
const { File: NodeFile } = require('node:buffer')

@@ -20,2 +20,14 @@ const File = globalThis.File ?? NodeFile ?? UndiciFile

/**
* @param {string} chars
*/
function isAsciiString (chars) {
for (let i = 0; i < chars.length; ++i) {
if ((chars.charCodeAt(i) & ~0x7F) !== 0) {
return false
}
}
return true
}
/**
* @see https://andreubotella.github.io/multipart-form-data/#multipart-form-data-boundary

@@ -35,3 +47,3 @@ * @param {string} boundary

// 0x2D (-) or 0x5F (_).
for (let i = 0; i < boundary.length; i++) {
for (let i = 0; i < length; ++i) {
const cp = boundary.charCodeAt(i)

@@ -64,3 +76,3 @@

// 1.1. Set name to the result of converting name into a scalar value string.
name = webidl.converters.USVString(name)
name = toUSVString(name)
} else {

@@ -70,3 +82,3 @@ // 2. Otherwise:

// 2.1. Assert: name is a scalar value string.
assert(name === webidl.converters.USVString(name))
assert(isUSVString(name))

@@ -102,10 +114,12 @@ // 2.2. Replace every occurrence of U+000D (CR) not followed by U+000A (LF),

const boundaryString = mimeType.parameters.get('boundary')
// 2. If mimeType’s parameters["boundary"] does not exist, return failure.
// Otherwise, let boundary be the result of UTF-8 decoding mimeType’s
// parameters["boundary"].
if (!mimeType.parameters.has('boundary')) {
if (boundaryString === undefined) {
return 'failure'
}
const boundary = Buffer.from(`--${mimeType.parameters.get('boundary')}`, 'utf8')
const boundary = Buffer.from(`--${boundaryString}`, 'utf8')

@@ -209,3 +223,6 @@ // 3. Let entry list be an empty entry list.

// 5.10.2. If contentType is not an ASCII string, set contentType to the empty string.
if (!isAscii(Buffer.from(contentType))) {
// Note: `buffer.isAscii` can be used at zero-cost, but converting a string to a buffer is a high overhead.
// Content-Type is a relatively small string, so it is faster to use `String#charCodeAt`.
if (!isAsciiString(contentType)) {
contentType = ''

@@ -224,4 +241,4 @@ }

// 5.12. Assert: name is a scalar value string and value is either a scalar value string or a File object.
assert(name === webidl.converters.USVString(name))
assert((typeof value === 'string' && value === webidl.converters.USVString(value)) || isFileLike(value))
assert(isUSVString(name))
assert((typeof value === 'string' && isUSVString(value)) || isFileLike(value))

@@ -291,3 +308,3 @@ // 5.13. Create an entry with name and value, and append it to entry list.

// 2.8. Byte-lowercase header name and switch on the result:
switch (new TextDecoder().decode(headerName).toLowerCase()) {
switch (bufferToLowerCasedHeaderName(headerName)) {
case 'content-disposition': {

@@ -440,6 +457,5 @@ // 1. Set name and filename to null.

const result = []
let index = 0
while (position.position < input.length && condition(input[position.position])) {
result[index++] = input[position.position]
result.push(input[position.position])

@@ -446,0 +462,0 @@ position.position++

@@ -15,2 +15,3 @@ // https://github.com/Ethan-Arrowood/undici-fetch

const assert = require('node:assert')
const util = require('util')

@@ -580,4 +581,14 @@ const kHeadersMap = Symbol('headers map')

}
[util.inspect.custom] (depth, options) {
const inspected = util.inspect(this[kHeadersList].entries)
return `Headers ${inspected}`
}
}
Object.defineProperty(Headers.prototype, util.inspect.custom, {
enumerable: false
})
iteratorMixin('Headers', Headers, kHeadersSortedMap, 0, 1)

@@ -584,0 +595,0 @@

{
"name": "undici",
"version": "6.7.1",
"version": "6.8.0",
"description": "An HTTP/1.1 client, written from scratch for Node.js",

@@ -110,2 +110,3 @@ "homepage": "https://undici.nodejs.org",

"jsfuzz": "^1.0.15",
"node-forge": "^1.3.1",
"pre-commit": "^1.2.2",

@@ -112,0 +113,0 @@ "proxy": "^2.1.1",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc