Socket
Socket
Sign inDemoInstall

undici

Package Overview
Dependencies
0
Maintainers
3
Versions
198
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 6.13.0 to 6.14.0

docs/docs/api/EnvHttpProxyAgent.md

30

docs/docs/api/EventSource.md
# EventSource
> ⚠️ Warning: the EventSource API is experimental.
Undici exposes a WHATWG spec-compliant implementation of [EventSource](https://developer.mozilla.org/en-US/docs/Web/API/EventSource)

@@ -14,4 +16,4 @@ for [Server-Sent Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events).

const evenSource = new EventSource('http://localhost:3000')
evenSource.onmessage = (event) => {
const eventSource = new EventSource('http://localhost:3000')
eventSource.onmessage = (event) => {
console.log(event.data)

@@ -21,3 +23,25 @@ }

## Using a custom Dispatcher
undici allows you to set your own Dispatcher in the EventSource constructor.
An example which allows you to modify the request headers is:
```mjs
import { EventSource, Agent } from 'undici'
class CustomHeaderAgent extends Agent {
dispatch (opts) {
opts.headers['x-custom-header'] = 'hello world'
return super.dispatch(...arguments)
}
}
const eventSource = new EventSource('http://localhost:3000', {
dispatcher: new CustomHeaderAgent()
})
```
More information about the EventSource API can be found on
[MDN](https://developer.mozilla.org/en-US/docs/Web/API/EventSource).
[MDN](https://developer.mozilla.org/en-US/docs/Web/API/EventSource).

6

docs/docs/api/Fetch.md

@@ -7,8 +7,2 @@ # Fetch

## File
This API is implemented as per the standard, you can find documentation on [MDN](https://developer.mozilla.org/en-US/docs/Web/API/File)
In Node versions v18.13.0 and above and v19.2.0 and above, undici will default to using Node's [File](https://nodejs.org/api/buffer.html#class-file) class. In versions where it's not available, it will default to the undici one.
## FormData

@@ -15,0 +9,0 @@

@@ -9,2 +9,3 @@ 'use strict'

const ProxyAgent = require('./lib/dispatcher/proxy-agent')
const EnvHttpProxyAgent = require('./lib/dispatcher/env-http-proxy-agent')
const RetryAgent = require('./lib/dispatcher/retry-agent')

@@ -34,2 +35,3 @@ const errors = require('./lib/core/errors')

module.exports.ProxyAgent = ProxyAgent
module.exports.EnvHttpProxyAgent = EnvHttpProxyAgent
module.exports.RetryAgent = RetryAgent

@@ -121,3 +123,3 @@ module.exports.RetryHandler = RetryHandler

module.exports.FormData = require('./lib/web/fetch/formdata').FormData
module.exports.File = require('./lib/web/fetch/file').File
module.exports.File = globalThis.File ?? require('node:buffer').File
module.exports.FileReader = require('./lib/web/fileapi/filereader').FileReader

@@ -124,0 +126,0 @@

@@ -15,9 +15,16 @@ const assert = require('node:assert')

for await (const chunk of body) {
chunks.push(chunk)
length += chunk.length
if (length > CHUNK_LIMIT) {
chunks = null
break
try {
for await (const chunk of body) {
chunks.push(chunk)
length += chunk.length
if (length > CHUNK_LIMIT) {
chunks = []
length = 0
break
}
}
} catch {
chunks = []
length = 0
// Do nothing....
}

@@ -27,3 +34,3 @@

if (statusCode === 204 || !contentType || !chunks) {
if (statusCode === 204 || !contentType || !length) {
queueMicrotask(() => callback(new ResponseStatusCodeError(message, statusCode, headers)))

@@ -30,0 +37,0 @@ return

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

isValidHTTPToken,
isValidHeaderChar,
isValidHeaderValue,
isStream,

@@ -340,3 +340,3 @@ destroy,

if (typeof val[i] === 'string') {
if (!isValidHeaderChar(val[i])) {
if (!isValidHeaderValue(val[i])) {
throw new InvalidArgumentError(`invalid ${key} header`)

@@ -355,3 +355,3 @@ }

} else if (typeof val === 'string') {
if (!isValidHeaderChar(val)) {
if (!isValidHeaderValue(val)) {
throw new InvalidArgumentError(`invalid ${key} header`)

@@ -361,4 +361,2 @@ }

val = ''
} else if (typeof val === 'object') {
throw new InvalidArgumentError(`invalid ${key} header`)
} else {

@@ -365,0 +363,0 @@ val = `${val}`

@@ -63,3 +63,6 @@ module.exports = {

kHTTPContext: Symbol('http context'),
kMaxConcurrentStreams: Symbol('max concurrent streams')
kMaxConcurrentStreams: Symbol('max concurrent streams'),
kNoProxyAgent: Symbol('no proxy agent'),
kHttpProxyAgent: Symbol('http proxy agent'),
kHttpsProxyAgent: Symbol('https proxy agent')
}

@@ -55,2 +55,28 @@ 'use strict'

function isValidPort (port) {
const value = parseInt(port, 10)
return (
value === Number(port) &&
value >= 0 &&
value <= 65535
)
}
function isHttpOrHttpsPrefixed (value) {
return (
value != null &&
value[0] === 'h' &&
value[1] === 't' &&
value[2] === 't' &&
value[3] === 'p' &&
(
value[4] === ':' ||
(
value[4] === 's' &&
value[5] === ':'
)
)
)
}
function parseURL (url) {

@@ -60,3 +86,3 @@ if (typeof url === 'string') {

if (!/^https?:/.test(url.origin || url.protocol)) {
if (!isHttpOrHttpsPrefixed(url.origin || url.protocol)) {
throw new InvalidArgumentError('Invalid URL protocol: the URL must start with `http:` or `https:`.')

@@ -72,8 +98,4 @@ }

if (!/^https?:/.test(url.origin || url.protocol)) {
throw new InvalidArgumentError('Invalid URL protocol: the URL must start with `http:` or `https:`.')
}
if (!(url instanceof URL)) {
if (url.port != null && url.port !== '' && !Number.isFinite(parseInt(url.port))) {
if (url.port != null && url.port !== '' && isValidPort(url.port) === false) {
throw new InvalidArgumentError('Invalid URL: port must be a valid integer or a string representation of an integer.')

@@ -98,2 +120,6 @@ }

if (!isHttpOrHttpsPrefixed(url.origin || url.protocol)) {
throw new InvalidArgumentError('Invalid URL protocol: the URL must start with `http:` or `https:`.')
}
const port = url.port != null

@@ -104,3 +130,3 @@ ? url.port

? url.origin
: `${url.protocol}//${url.hostname}:${port}`
: `${url.protocol || ''}//${url.hostname || ''}:${port}`
let path = url.path != null

@@ -110,7 +136,7 @@ ? url.path

if (origin.endsWith('/')) {
origin = origin.substring(0, origin.length - 1)
if (origin[origin.length - 1] === '/') {
origin = origin.slice(0, origin.length - 1)
}
if (path && !path.startsWith('/')) {
if (path && path[0] !== '/') {
path = `/${path}`

@@ -122,5 +148,9 @@ }

// If first parameter is an absolute URL, a given second param will be ignored.
url = new URL(origin + path)
return new URL(`${origin}${path}`)
}
if (!isHttpOrHttpsPrefixed(url.origin || url.protocol)) {
throw new InvalidArgumentError('Invalid URL protocol: the URL must start with `http:` or `https:`.')
}
return url

@@ -203,7 +233,2 @@ }

function isReadableAborted (stream) {
const state = stream?._readableState
return isDestroyed(stream) && state && !state.endEmitted
}
function destroy (stream, err) {

@@ -533,3 +558,3 @@ if (stream == null || !isStream(stream) || isDestroyed(stream)) {

*/
function isValidHeaderChar (characters) {
function isValidHeaderValue (characters) {
return !headerCharRegex.test(characters)

@@ -587,3 +612,2 @@ }

isUSVString,
isReadableAborted,
isBlobLike,

@@ -616,9 +640,10 @@ parseOrigin,

isValidHTTPToken,
isValidHeaderChar,
isValidHeaderValue,
isTokenCharCode,
parseRangeHeader,
isValidPort,
isHttpOrHttpsPrefixed,
nodeMajor,
nodeMinor,
nodeHasAutoSelectFamily: nodeMajor > 18 || (nodeMajor === 18 && nodeMinor >= 13),
safeHTTPMethods: ['GET', 'HEAD', 'OPTIONS', 'TRACE']
}

@@ -211,6 +211,5 @@ 'use strict'

* along with the socket right away
* Find a way to trigger the close cycle from here on.
*/
function onHTTP2GoAway (code) {
const err = new InformationalError(`HTTP/2: "GOAWAY" frame received with code ${code}`)
const err = new RequestAbortedError(`HTTP/2: "GOAWAY" frame received with code ${code}`)

@@ -224,4 +223,3 @@ // We need to trigger the close cycle right away

this.unref()
// We send the GOAWAY frame response as no error
this.destroy()
util.destroy(this[kSocket], err)

@@ -228,0 +226,0 @@ }

@@ -206,3 +206,3 @@ // @ts-check

timeout: connectTimeout,
...(util.nodeHasAutoSelectFamily && autoSelectFamily ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : undefined),
...(autoSelectFamily ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : undefined),
...connect

@@ -380,2 +380,3 @@ })

const requests = client[kQueue].splice(client[kRunningIdx])
for (let i = 0; i < requests.length; i++) {

@@ -382,0 +383,0 @@ const request = requests[i]

@@ -9,6 +9,4 @@ 'use strict'

} = require('../core/errors')
const { kDestroy, kClose, kDispatch, kInterceptors } = require('../core/symbols')
const { kDestroy, kClose, kClosed, kDestroyed, kDispatch, kInterceptors } = require('../core/symbols')
const kDestroyed = Symbol('destroyed')
const kClosed = Symbol('closed')
const kOnDestroyed = Symbol('onDestroyed')

@@ -15,0 +13,0 @@ const kOnClosed = Symbol('onClosed')

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

timeout: connectTimeout,
...(util.nodeHasAutoSelectFamily && autoSelectFamily ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : undefined),
...(autoSelectFamily ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : undefined),
...connect

@@ -64,0 +64,0 @@ })

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

new AbortController().signal,
'immutable',
{ settingsObject: request.client }
'immutable'
)

@@ -783,3 +782,3 @@ // 5.4.2.1

// 5.5.2.1
const responseObject = fromInnerResponse(response, 'immutable', { settingsObject: {} })
const responseObject = fromInnerResponse(response, 'immutable')

@@ -786,0 +785,0 @@ responseList.push(responseObject.clone())

@@ -6,3 +6,2 @@ 'use strict'

const { makeRequest } = require('../fetch/request')
const { getGlobalOrigin } = require('../fetch/global')
const { webidl } = require('../fetch/webidl')

@@ -15,2 +14,3 @@ const { EventSourceStream } = require('./eventsource-stream')

const { kEnumerableProperty } = require('../../core/util')
const { environmentSettingsObject } = require('../fetch/util')

@@ -71,8 +71,2 @@ let experimentalWarned = false

/**
* @typedef {object} EventSourceInit
* @property {boolean} [withCredentials] indicates whether the request
* should include credentials.
*/
/**
* The EventSource interface is used to receive server-sent events. It

@@ -100,9 +94,8 @@ * connects to a server over HTTP and receives events in text/event-stream

#dispatcher
/**
* @type {object}
* @property {string} lastEventId
* @property {number} reconnectionTime
* @property {any} reconnectionTimer
* @type {import('./eventsource-stream').eventSourceSettings}
*/
#settings = null
#state

@@ -131,9 +124,4 @@ /**

// 2. Let settings be ev's relevant settings object.
// https://html.spec.whatwg.org/multipage/webappapis.html#environment-settings-object
this.#settings = {
origin: getGlobalOrigin(),
policyContainer: {
referrerPolicy: 'no-referrer'
},
this.#dispatcher = eventSourceInitDict.dispatcher
this.#state = {
lastEventId: '',

@@ -143,2 +131,6 @@ reconnectionTime: defaultReconnectionTime

// 2. Let settings be ev's relevant settings object.
// https://html.spec.whatwg.org/multipage/webappapis.html#environment-settings-object
const settings = environmentSettingsObject
let urlRecord

@@ -148,4 +140,4 @@

// 3. Let urlRecord be the result of encoding-parsing a URL given url, relative to settings.
urlRecord = new URL(url, this.#settings.origin)
this.#settings.origin = urlRecord.origin
urlRecord = new URL(url, settings.settingsObject.baseUrl)
this.#state.origin = urlRecord.origin
} catch (e) {

@@ -184,3 +176,3 @@ // 4. If urlRecord is failure, then throw a "SyntaxError" DOMException.

// 9. Set request's client to settings.
initRequest.client = this.#settings
initRequest.client = environmentSettingsObject.settingsObject

@@ -236,4 +228,5 @@ // 10. User agents may set (`Accept`, `text/event-stream`) in request's header list.

const fetchParam = {
request: this.#request
const fetchParams = {
request: this.#request,
dispatcher: this.#dispatcher
}

@@ -252,6 +245,6 @@

// 15. Fetch request, with processResponseEndOfBody set to processEventSourceEndOfBody...
fetchParam.processResponseEndOfBody = processEventSourceEndOfBody
fetchParams.processResponseEndOfBody = processEventSourceEndOfBody
// and processResponse set to the following steps given response res:
fetchParam.processResponse = (response) => {
fetchParams.processResponse = (response) => {
// 1. If res is an aborted network error, then fail the connection.

@@ -305,6 +298,6 @@

// If redirected to a different origin, set the origin to the new origin.
this.#settings.origin = response.urlList[response.urlList.length - 1].origin
this.#state.origin = response.urlList[response.urlList.length - 1].origin
const eventSourceStream = new EventSourceStream({
eventSourceSettings: this.#settings,
eventSourceSettings: this.#state,
push: (event) => {

@@ -330,3 +323,3 @@ this.dispatchEvent(new MessageEvent(

this.#controller = fetching(fetchParam)
this.#controller = fetching(fetchParams)
}

@@ -356,3 +349,3 @@

// 2. Wait a delay equal to the reconnection time of the event source.
await delay(this.#settings.reconnectionTime)
await delay(this.#state.reconnectionTime)

@@ -372,4 +365,4 @@ // 5. Queue a task to run the following steps:

// list.
if (this.#settings.lastEventId !== '') {
this.#request.headersList.set('last-event-id', this.#settings.lastEventId, true)
if (this.#state.lastEventId.length) {
this.#request.headersList.set('last-event-id', this.#state.lastEventId, true)
}

@@ -390,8 +383,4 @@

this.#readyState = CLOSED
clearTimeout(this.#settings.reconnectionTimer)
this.#controller.abort()
if (this.#request) {
this.#request = null
}
this.#request = null
}

@@ -489,3 +478,11 @@

webidl.converters.EventSourceInitDict = webidl.dictionaryConverter([
{ key: 'withCredentials', converter: webidl.converters.boolean, defaultValue: false }
{
key: 'withCredentials',
converter: webidl.converters.boolean,
defaultValue: false
},
{
key: 'dispatcher', // undici only
converter: webidl.converters.any
}
])

@@ -492,0 +489,0 @@

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

return new Blob([bytes], { type: mimeType })
}, instance)
}, instance, false)
},

@@ -322,4 +322,5 @@

return consumeBody(this, (bytes) => {
return new Uint8Array(bytes).buffer
}, instance)
// Note: arrayBuffer already cloned.
return bytes.buffer
}, instance, true)
},

@@ -330,3 +331,3 @@

// consume body with this and UTF-8 decode.
return consumeBody(this, utf8DecodeBytes, instance)
return consumeBody(this, utf8DecodeBytes, instance, false)
},

@@ -337,3 +338,3 @@

// consume body with this and parse JSON from bytes.
return consumeBody(this, parseJSONFromBytes, instance)
return consumeBody(this, parseJSONFromBytes, instance, false)
},

@@ -390,3 +391,3 @@

)
}, instance)
}, instance, false)
}

@@ -407,4 +408,5 @@ }

* @param {Response|Request} instance
* @param {boolean} [shouldClone]
*/
async function consumeBody (object, convertBytesToJSValue, instance) {
async function consumeBody (object, convertBytesToJSValue, instance, shouldClone) {
webidl.brandCheck(object, instance)

@@ -415,3 +417,3 @@

if (bodyUnusable(object[kState].body)) {
throw new TypeError('Body is unusable')
throw new TypeError('Body is unusable: Body has already been read')
}

@@ -442,3 +444,3 @@

if (object[kState].body == null) {
successSteps(new Uint8Array())
successSteps(Buffer.allocUnsafe(0))
return promise.promise

@@ -449,3 +451,3 @@ }

// errorSteps, and object’s relevant global object.
await fullyReadBody(object[kState].body, successSteps, errorSteps)
await fullyReadBody(object[kState].body, successSteps, errorSteps, shouldClone)

@@ -452,0 +454,0 @@ // 7. Return promise.

'use strict'
const { EOL } = require('node:os')
const { Blob, File: NativeFile } = require('node:buffer')
const { types } = require('node:util')
const { Blob, File } = require('node:buffer')
const { kState } = require('./symbols')
const { isBlobLike } = require('./util')
const { webidl } = require('./webidl')
const { parseMIMEType, serializeAMimeType } = require('./data-url')
const { kEnumerableProperty } = require('../../core/util')
const encoder = new TextEncoder()
class File extends Blob {
constructor (fileBits, fileName, options = {}) {
// The File constructor is invoked with two or three parameters, depending
// on whether the optional dictionary parameter is used. When the File()
// constructor is invoked, user agents must run the following steps:
webidl.argumentLengthCheck(arguments, 2, { header: 'File constructor' })
fileBits = webidl.converters['sequence<BlobPart>'](fileBits)
fileName = webidl.converters.USVString(fileName)
options = webidl.converters.FilePropertyBag(options)
// 1. Let bytes be the result of processing blob parts given fileBits and
// options.
// Note: Blob handles this for us
// 2. Let n be the fileName argument to the constructor.
const n = fileName
// 3. Process FilePropertyBag dictionary argument by running the following
// substeps:
// 1. If the type member is provided and is not the empty string, let t
// be set to the type dictionary member. If t contains any characters
// outside the range U+0020 to U+007E, then set t to the empty string
// and return from these substeps.
// 2. Convert every character in t to ASCII lowercase.
let t = options.type
let d
// eslint-disable-next-line no-labels
substep: {
if (t) {
t = parseMIMEType(t)
if (t === 'failure') {
t = ''
// eslint-disable-next-line no-labels
break substep
}
t = serializeAMimeType(t).toLowerCase()
}
// 3. If the lastModified member is provided, let d be set to the
// lastModified dictionary member. If it is not provided, set d to the
// current date and time represented as the number of milliseconds since
// the Unix Epoch (which is the equivalent of Date.now() [ECMA-262]).
d = options.lastModified
}
// 4. Return a new File object F such that:
// F refers to the bytes byte sequence.
// F.size is set to the number of total bytes in bytes.
// F.name is set to n.
// F.type is set to t.
// F.lastModified is set to d.
super(processBlobParts(fileBits, options), { type: t })
this[kState] = {
name: n,
lastModified: d,
type: t
}
}
get name () {
webidl.brandCheck(this, File)
return this[kState].name
}
get lastModified () {
webidl.brandCheck(this, File)
return this[kState].lastModified
}
get type () {
webidl.brandCheck(this, File)
return this[kState].type
}
}
// TODO(@KhafraDev): remove
class FileLike {

@@ -199,125 +109,4 @@ constructor (blobLike, fileName, options = {}) {

Object.defineProperties(File.prototype, {
[Symbol.toStringTag]: {
value: 'File',
configurable: true
},
name: kEnumerableProperty,
lastModified: kEnumerableProperty
})
webidl.converters.Blob = webidl.interfaceConverter(Blob)
webidl.converters.BlobPart = function (V, opts) {
if (webidl.util.Type(V) === 'Object') {
if (isBlobLike(V)) {
return webidl.converters.Blob(V, { strict: false })
}
if (ArrayBuffer.isView(V) || types.isAnyArrayBuffer(V)) {
return webidl.converters.BufferSource(V, opts)
}
}
return webidl.converters.USVString(V, opts)
}
webidl.converters['sequence<BlobPart>'] = webidl.sequenceConverter(
webidl.converters.BlobPart
)
// https://www.w3.org/TR/FileAPI/#dfn-FilePropertyBag
webidl.converters.FilePropertyBag = webidl.dictionaryConverter([
{
key: 'lastModified',
converter: webidl.converters['long long'],
get defaultValue () {
return Date.now()
}
},
{
key: 'type',
converter: webidl.converters.DOMString,
defaultValue: ''
},
{
key: 'endings',
converter: (value) => {
value = webidl.converters.DOMString(value)
value = value.toLowerCase()
if (value !== 'native') {
value = 'transparent'
}
return value
},
defaultValue: 'transparent'
}
])
/**
* @see https://www.w3.org/TR/FileAPI/#process-blob-parts
* @param {(NodeJS.TypedArray|Blob|string)[]} parts
* @param {{ type: string, endings: string }} options
*/
function processBlobParts (parts, options) {
// 1. Let bytes be an empty sequence of bytes.
/** @type {NodeJS.TypedArray[]} */
const bytes = []
// 2. For each element in parts:
for (const element of parts) {
// 1. If element is a USVString, run the following substeps:
if (typeof element === 'string') {
// 1. Let s be element.
let s = element
// 2. If the endings member of options is "native", set s
// to the result of converting line endings to native
// of element.
if (options.endings === 'native') {
s = convertLineEndingsNative(s)
}
// 3. Append the result of UTF-8 encoding s to bytes.
bytes.push(encoder.encode(s))
} else if (ArrayBuffer.isView(element) || types.isArrayBuffer(element)) {
// 2. If element is a BufferSource, get a copy of the
// bytes held by the buffer source, and append those
// bytes to bytes.
if (element.buffer) {
bytes.push(
new Uint8Array(element.buffer, element.byteOffset, element.byteLength)
)
} else { // ArrayBuffer
bytes.push(new Uint8Array(element))
}
} else if (isBlobLike(element)) {
// 3. If element is a Blob, append the bytes it represents
// to bytes.
bytes.push(element)
}
}
// 3. Return bytes.
return bytes
}
/**
* @see https://www.w3.org/TR/FileAPI/#convert-line-endings-to-native
* @param {string} s
*/
function convertLineEndingsNative (s) {
// 1. Let native line ending be be the code point U+000A LF.
// 2. If the underlying platform’s conventions are to
// represent newlines as a carriage return and line feed
// sequence, set native line ending to the code point
// U+000D CR followed by the code point U+000A LF.
// NOTE: We are using the native line ending for the current
// platform, provided by node's os module.
return s.replace(/\r?\n/g, EOL)
}
// If this function is moved to ./util.js, some tools (such as

@@ -328,4 +117,4 @@ // rollup) will warn about circular dependencies. See:

return (
(NativeFile && object instanceof NativeFile) ||
object instanceof File || (
(object instanceof File) ||
(
object &&

@@ -339,2 +128,2 @@ (typeof object.stream === 'function' ||

module.exports = { File, FileLike, isFileLike }
module.exports = { FileLike, isFileLike }

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

const { HTTP_TOKEN_CODEPOINTS, isomorphicDecode } = require('./data-url')
const { isFileLike, File: UndiciFile } = require('./file')
const { isFileLike } = require('./file')
const { makeEntry } = require('./formdata')

@@ -12,3 +12,3 @@ const assert = require('node:assert')

const File = globalThis.File ?? NodeFile ?? UndiciFile
const File = globalThis.File ?? NodeFile

@@ -15,0 +15,0 @@ const formDataNameBuffer = Buffer.from('form-data; name="')

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

const { kEnumerableProperty } = require('../../core/util')
const { File: UndiciFile, FileLike, isFileLike } = require('./file')
const { FileLike, isFileLike } = require('./file')
const { webidl } = require('./webidl')

@@ -13,3 +13,3 @@ const { File: NativeFile } = require('node:buffer')

/** @type {globalThis['File']} */
const File = NativeFile ?? UndiciFile
const File = globalThis.File ?? NativeFile

@@ -236,3 +236,3 @@ // https://xhr.spec.whatwg.org/#formdata

value = (NativeFile && value instanceof NativeFile) || value instanceof UndiciFile
value = value instanceof NativeFile
? new File([value], filename, options)

@@ -239,0 +239,0 @@ : new FileLike(value, filename, options)

@@ -14,3 +14,3 @@ /* globals AbortController */

normalizeMethod,
makePolicyContainer,
environmentSettingsObject,
normalizeMethodRecord

@@ -29,5 +29,4 @@ } = require('./util')

const { kEnumerableProperty } = util
const { kHeaders, kSignal, kState, kGuard, kRealm, kDispatcher } = require('./symbols')
const { kHeaders, kSignal, kState, kGuard, kDispatcher } = require('./symbols')
const { webidl } = require('./webidl')
const { getGlobalOrigin } = require('./global')
const { URLSerializer } = require('./data-url')

@@ -59,13 +58,2 @@ const { kHeadersList, kConstruct } = require('../../core/symbols')

// https://html.spec.whatwg.org/multipage/webappapis.html#environment-settings-object
this[kRealm] = {
settingsObject: {
baseUrl: getGlobalOrigin(),
get origin () {
return this.baseUrl?.origin
},
policyContainer: makePolicyContainer()
}
}
// 1. Let request be null.

@@ -78,3 +66,3 @@ let request = null

// 3. Let baseURL be this’s relevant settings object’s API base URL.
const baseUrl = this[kRealm].settingsObject.baseUrl
const baseUrl = environmentSettingsObject.settingsObject.baseUrl

@@ -126,3 +114,3 @@ // 4. Let signal be null.

// 7. Let origin be this’s relevant settings object’s origin.
const origin = this[kRealm].settingsObject.origin
const origin = environmentSettingsObject.settingsObject.origin

@@ -163,3 +151,3 @@ // 8. Let window be "client".

// client This’s relevant settings object.
client: this[kRealm].settingsObject,
client: environmentSettingsObject.settingsObject,
// window window.

@@ -253,3 +241,3 @@ window,

(parsedReferrer.protocol === 'about:' && parsedReferrer.hostname === 'client') ||
(origin && !sameOrigin(parsedReferrer, this[kRealm].settingsObject.baseUrl))
(origin && !sameOrigin(parsedReferrer, environmentSettingsObject.settingsObject.baseUrl))
) {

@@ -376,3 +364,2 @@ request.referrer = 'client'

this[kSignal] = ac.signal
this[kSignal][kRealm] = this[kRealm]

@@ -447,3 +434,2 @@ // 29. If signal is not null, then make this’s signal follow signal.

this[kHeaders][kGuard] = 'request'
this[kHeaders][kRealm] = this[kRealm]

@@ -782,3 +768,3 @@ // 31. If this’s request’s mode is "no-cors", then:

// 4. Return clonedRequestObject.
return fromInnerRequest(clonedRequest, ac.signal, this[kHeaders][kGuard], this[kRealm])
return fromInnerRequest(clonedRequest, ac.signal, this[kHeaders][kGuard])
}

@@ -886,15 +872,11 @@

* @param {'request' | 'immutable' | 'request-no-cors' | 'response' | 'none'} guard
* @param {any} [realm]
* @returns {Request}
*/
function fromInnerRequest (innerRequest, signal, guard, realm) {
function fromInnerRequest (innerRequest, signal, guard) {
const request = new Request(kConstruct)
request[kState] = innerRequest
request[kRealm] = realm
request[kSignal] = signal
request[kSignal][kRealm] = realm
request[kHeaders] = new Headers(kConstruct)
request[kHeaders][kHeadersList] = innerRequest.headersList
request[kHeaders][kGuard] = guard
request[kHeaders][kRealm] = realm
return request

@@ -901,0 +883,0 @@ }

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

isErrorLike,
isomorphicEncode
isomorphicEncode,
environmentSettingsObject: relevantRealm
} = require('./util')

@@ -22,6 +23,5 @@ const {

} = require('./constants')
const { kState, kHeaders, kGuard, kRealm } = require('./symbols')
const { kState, kHeaders, kGuard } = require('./symbols')
const { webidl } = require('./webidl')
const { FormData } = require('./formdata')
const { getGlobalOrigin } = require('./global')
const { URLSerializer } = require('./data-url')

@@ -38,9 +38,6 @@ const { kHeadersList, kConstruct } = require('../../core/symbols')

static error () {
// TODO
const relevantRealm = { settingsObject: {} }
// The static error() method steps are to return the result of creating a
// Response object, given a new network error, "immutable", and this’s
// relevant Realm.
const responseObject = fromInnerResponse(makeNetworkError(), 'immutable', relevantRealm)
const responseObject = fromInnerResponse(makeNetworkError(), 'immutable')

@@ -68,4 +65,3 @@ return responseObject

// "response", and this’s relevant Realm.
const relevantRealm = { settingsObject: {} }
const responseObject = fromInnerResponse(makeResponse({}), 'response', relevantRealm)
const responseObject = fromInnerResponse(makeResponse({}), 'response')

@@ -81,4 +77,2 @@ // 4. Perform initialize a response given responseObject, init, and (body, "application/json").

static redirect (url, status = 302) {
const relevantRealm = { settingsObject: {} }
webidl.argumentLengthCheck(arguments, 1, { header: 'Response.redirect' })

@@ -95,3 +89,3 @@

try {
parsedURL = new URL(url, getGlobalOrigin())
parsedURL = new URL(url, relevantRealm.settingsObject.baseUrl)
} catch (err) {

@@ -108,3 +102,3 @@ throw new TypeError(`Failed to parse URL from ${url}`, { cause: err })

// given a new response, "immutable", and this’s relevant Realm.
const responseObject = fromInnerResponse(makeResponse({}), 'immutable', relevantRealm)
const responseObject = fromInnerResponse(makeResponse({}), 'immutable')

@@ -136,5 +130,2 @@ // 5. Set responseObject’s response’s status to status.

// TODO
this[kRealm] = { settingsObject: {} }
// 1. Set this’s response to a new response.

@@ -149,3 +140,2 @@ this[kState] = makeResponse({})

this[kHeaders][kHeadersList] = this[kState].headersList
this[kHeaders][kRealm] = this[kRealm]

@@ -263,3 +253,3 @@ // 3. Let bodyWithType be null.

// clonedResponse, this’s headers’s guard, and this’s relevant Realm.
return fromInnerResponse(clonedResponse, this[kHeaders][kGuard], this[kRealm])
return fromInnerResponse(clonedResponse, this[kHeaders][kGuard])
}

@@ -525,13 +515,10 @@

* @param {'request' | 'immutable' | 'request-no-cors' | 'response' | 'none'} guard
* @param {any} [realm]
* @returns {Response}
*/
function fromInnerResponse (innerResponse, guard, realm) {
function fromInnerResponse (innerResponse, guard) {
const response = new Response(kConstruct)
response[kState] = innerResponse
response[kRealm] = realm
response[kHeaders] = new Headers(kConstruct)
response[kHeaders][kHeadersList] = innerResponse.headersList
response[kHeaders][kGuard] = guard
response[kHeaders][kRealm] = realm
return response

@@ -538,0 +525,0 @@ }

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

kGuard: Symbol('guard'),
kRealm: Symbol('realm'),
kDispatcher: Symbol('dispatcher')
}

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

*/
async function fullyReadBody (body, processBody, processBodyError) {
async function fullyReadBody (body, processBody, processBodyError, shouldClone) {
// 1. If taskDestination is null, then set taskDestination to

@@ -1073,4 +1073,3 @@ // the result of starting a new parallel queue.

try {
const result = await readAllBytes(reader)
successSteps(result)
successSteps(await readAllBytes(reader, shouldClone))
} catch (e) {

@@ -1103,2 +1102,4 @@ errorSteps(e)

const invalidIsomorphicEncodeValueRegex = /[^\x00-\xFF]/ // eslint-disable-line
/**

@@ -1110,5 +1111,3 @@ * @see https://infra.spec.whatwg.org/#isomorphic-encode

// 1. Assert: input contains no code points greater than U+00FF.
for (let i = 0; i < input.length; i++) {
assert(input.charCodeAt(i) <= 0xFF)
}
assert(!invalidIsomorphicEncodeValueRegex.test(input))

@@ -1125,4 +1124,5 @@ // 2. Return a byte sequence whose length is equal to input’s code

* @param {ReadableStreamDefaultReader} reader
* @param {boolean} [shouldClone]
*/
async function readAllBytes (reader) {
async function readAllBytes (reader, shouldClone) {
const bytes = []

@@ -1136,2 +1136,9 @@ let byteLength = 0

// 1. Call successSteps with bytes.
if (bytes.length === 1) {
const { buffer, byteOffset, byteLength } = bytes[0]
if (shouldClone === false) {
return Buffer.from(buffer, byteOffset, byteLength)
}
return Buffer.from(buffer.slice(byteOffset, byteOffset + byteLength), 0, byteLength)
}
return Buffer.concat(bytes, byteLength)

@@ -1571,2 +1578,20 @@ }

class EnvironmentSettingsObjectBase {
get baseUrl () {
return getGlobalOrigin()
}
get origin () {
return this.baseUrl?.origin
}
policyContainer = makePolicyContainer()
}
class EnvironmentSettingsObject {
settingsObject = new EnvironmentSettingsObjectBase()
}
const environmentSettingsObject = new EnvironmentSettingsObject()
module.exports = {

@@ -1623,3 +1648,4 @@ isAborted,

getDecodeSplit,
utf8DecodeBytes
utf8DecodeBytes,
environmentSettingsObject
}

@@ -214,15 +214,8 @@ 'use strict'

? fatalDecoder.decode.bind(fatalDecoder)
: !isUtf8
? function () { // TODO: remove once node 18 or < node v18.14.0 is dropped
process.emitWarning('ICU is not supported and no fallback exists. Please upgrade to at least Node v18.14.0.', {
code: 'UNDICI-WS-NO-ICU'
})
throw new TypeError('Invalid utf-8 received.')
}
: function (buffer) {
if (isUtf8(buffer)) {
return buffer.toString('utf-8')
}
throw new TypeError('Invalid utf-8 received.')
}
: function (buffer) {
if (isUtf8(buffer)) {
return buffer.toString('utf-8')
}
throw new TypeError('Invalid utf-8 received.')
}

@@ -229,0 +222,0 @@ module.exports = {

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

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

"abort-controller": "^3.0.0",
"borp": "^0.10.0",
"borp": "^0.11.0",
"c8": "^9.1.0",

@@ -122,2 +122,3 @@ "cross-env": "^7.0.3",

"proxy": "^2.1.1",
"sinon": "^17.0.1",
"snazzy": "^9.0.0",

@@ -130,3 +131,3 @@ "standard": "^17.0.0",

"engines": {
"node": ">=18.0"
"node": ">=18.17"
},

@@ -133,0 +134,0 @@ "standard": {

@@ -220,3 +220,3 @@ import { URL } from 'url'

/** Invoked before request is dispatched on socket. May be invoked multiple times when a request is retried when the request at the head of the pipeline fails. */
onConnect?(abort: () => void): void;
onConnect?(abort: (err?: Error) => void): void;
/** Invoked when an error has occurred. */

@@ -223,0 +223,0 @@ onError?(err: Error): void;

import { MessageEvent, ErrorEvent } from './websocket'
import Dispatcher from './dispatcher'

@@ -53,3 +54,3 @@ import {

prototype: EventSource
new (url: string | URL, init: EventSourceInit): EventSource
new (url: string | URL, init?: EventSourceInit): EventSource
readonly CLOSED: 2

@@ -61,3 +62,4 @@ readonly CONNECTING: 0

interface EventSourceInit {
withCredentials?: boolean
withCredentials?: boolean,
dispatcher?: Dispatcher
}

@@ -17,2 +17,3 @@ import Dispatcher from'./dispatcher'

import ProxyAgent from'./proxy-agent'
import EnvHttpProxyAgent from './env-http-proxy-agent'
import RetryHandler from'./retry-handler'

@@ -35,3 +36,3 @@ import RetryAgent from'./retry-agent'

export { Dispatcher, BalancedPool, Pool, Client, buildConnector, errors, Agent, request, stream, pipeline, connect, upgrade, setGlobalDispatcher, getGlobalDispatcher, setGlobalOrigin, getGlobalOrigin, MockClient, MockPool, MockAgent, mockErrors, ProxyAgent, RedirectHandler, DecoratorHandler, RetryHandler, RetryAgent }
export { Dispatcher, BalancedPool, Pool, Client, buildConnector, errors, Agent, request, stream, pipeline, connect, upgrade, setGlobalDispatcher, getGlobalDispatcher, setGlobalOrigin, getGlobalOrigin, MockClient, MockPool, MockAgent, mockErrors, ProxyAgent, EnvHttpProxyAgent, RedirectHandler, DecoratorHandler, RetryHandler, RetryAgent }
export default Undici

@@ -38,0 +39,0 @@

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

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

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc