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 4.4.2 to 4.4.3

2

lib/agent.js

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

const { maxRedirections = this[kMaxRedirections] } = opts
if (maxRedirections != null) {
if (maxRedirections != null && maxRedirections !== 0) {
opts = { ...opts, maxRedirections: 0 } // Stop sub dispatcher from also redirecting.

@@ -140,0 +140,0 @@ handler = new RedirectHandler(this, maxRedirections, opts, handler)

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

if (body.resume) {
body.resume()
}
socket

@@ -1530,0 +1534,0 @@ .on('drain', onDrain)

@@ -197,11 +197,2 @@ 'use strict'

class InvalidThisError extends TypeError {
constructor (type) {
super(`Value of "this" must be of type ${type}`)
Error.captureStackTrace(this, InvalidThisError)
this.name = 'InvalidThis'
this.code = 'INVALID_THIS'
}
}
module.exports = {

@@ -227,4 +218,3 @@ AbortError,

InvalidHTTPTokenError,
HTTPInvalidHeaderValueError,
InvalidThisError
HTTPInvalidHeaderValueError
}

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

const { NotSupportedError } = require('../core/errors')
const { ReadableStream } = require('stream/web')
const { kBodyUsed } = require('../core/symbols')

@@ -15,4 +14,10 @@ const assert = require('assert')

let ReadableStream
// https://fetch.spec.whatwg.org/#concept-bodyinit-extract
function extractBody (object, keepalive = false) {
if (!ReadableStream) {
ReadableStream = require('stream/web').ReadableStream
}
// 1. Let stream be object if object is a ReadableStream object.

@@ -90,3 +95,4 @@ // Otherwise, let stream be a new ReadableStream, and set up stream.

// If object’s type attribute is not the empty byte sequence, set Content-Type to its value.
// If object’s type attribute is not the empty byte sequence, set
// Content-Type to its value.
if (object.type) {

@@ -113,10 +119,6 @@ contentType = object.type

}
} else if (typeof object === 'string') {
// scalar value string
// TODO: How to check for "scalar value string"?
source = object
contentType = 'text/plain;charset=UTF-8'
} else {
// TODO: byte sequence?
// TODO: FormData?
// TODO: scalar value string?
// TODO: else?

@@ -152,3 +154,6 @@ source = String(object)

// When running action is done, close stream.
controller.close()
queueMicrotask(() => {
// See https://github.com/nodejs/node/issues/39758
controller.close()
})
}

@@ -159,3 +164,6 @@ )

controller.enqueue(source)
controller.close()
queueMicrotask(() => {
// See https://github.com/nodejs/node/issues/39758
controller.close()
})
}

@@ -173,2 +181,6 @@

function safelyExtractBody (object, keepalive = false) {
if (!ReadableStream) {
ReadableStream = require('stream/web').ReadableStream
}
// To safely extract a body and a `Content-Type` value from

@@ -268,2 +280,15 @@ // a byte sequence or BodyInit object object, run these steps:

function cancelBody (body, reason) {
try {
if (body.stream) {
body.stream.cancel(reason)
}
} catch (err) {
// Will throw TypeError if body is not readable.
if (err.name !== 'TypeError') {
throw err
}
}
}
function mixinBody (prototype) {

@@ -275,2 +300,3 @@ Object.assign(prototype, methods)

module.exports = {
cancelBody,
extractBody,

@@ -277,0 +303,0 @@ safelyExtractBody,

@@ -73,3 +73,19 @@ 'use strict'

const subresource = [
'audio',
'audioworklet',
'font',
'image',
'manifest',
'paintworklet',
'script',
'style',
'track',
'video',
'xslt',
''
]
module.exports = {
subresource,
forbiddenResponseHeaderNames,

@@ -76,0 +92,0 @@ forbiddenMethods,

@@ -11,4 +11,3 @@ // https://github.com/Ethan-Arrowood/undici-fetch

InvalidHTTPTokenError,
HTTPInvalidHeaderValueError,
InvalidThisError
HTTPInvalidHeaderValueError
} = require('../core/errors')

@@ -58,6 +57,2 @@ const {

function isHeaders (object) {
return kHeadersList in object
}
function fill (headers, object) {

@@ -105,17 +100,5 @@ // To fill a Headers object headers with a given object object, run these steps:

function validateArgumentLength (found, expected) {
if (found !== expected) {
throw new TypeError(
`${expected} ${
expected > 1 ? 'arguments' : 'argument'
} required, but only ${found} present`
)
}
}
// TODO: Composition over inheritence? Or helper methods?
class HeadersList extends Array {
append (...args) {
validateArgumentLength(args.length, 2)
const [name, value] = args
append (name, value) {
const normalizedName = normalizeAndValidateHeaderName(name)

@@ -133,7 +116,3 @@ const normalizedValue = normalizeAndValidateHeaderValue(name, value)

delete (...args) {
validateArgumentLength(args.length, 1)
const [name] = args
delete (name) {
const normalizedName = normalizeAndValidateHeaderName(name)

@@ -148,7 +127,3 @@

get (...args) {
validateArgumentLength(args.length, 1)
const [name] = args
get (name) {
const normalizedName = normalizeAndValidateHeaderName(name)

@@ -165,7 +140,3 @@

has (...args) {
validateArgumentLength(args.length, 1)
const [name] = args
has (name) {
const normalizedName = normalizeAndValidateHeaderName(name)

@@ -178,7 +149,3 @@

set (...args) {
validateArgumentLength(args.length, 2)
const [name, value] = args
set (name, value) {
const normalizedName = normalizeAndValidateHeaderName(name)

@@ -197,3 +164,12 @@ const normalizedValue = normalizeAndValidateHeaderValue(name, value)

class Headers {
constructor (init = {}) {
constructor (...args) {
if (
args[0] !== undefined &&
!(typeof args[0] === 'object' && args[0] !== null) &&
!Array.isArray(args[0])
) {
throw new TypeError("Failed to construct 'Headers': The provided value is not of type '(record<ByteString, ByteString> or sequence<sequence<ByteString>>")
}
const init = args.length >= 1 ? (args[0] ?? {}) : {}
this[kHeadersList] = new HeadersList()

@@ -207,6 +183,10 @@

// 2. If init is given, then fill this with init.
fill(this[kHeadersList], init)
fill(this, init)
}
get [Symbol.toStringTag] () {
if (!(this instanceof Headers)) {
throw new TypeError('Illegal invocation')
}
return this.constructor.name

@@ -216,2 +196,6 @@ }

toString () {
if (!(this instanceof Headers)) {
throw new TypeError('Illegal invocation')
}
return Object.prototype.toString.call(this)

@@ -221,7 +205,10 @@ }

append (...args) {
if (!isHeaders(this)) {
throw new InvalidThisError('Header')
if (!(this instanceof Headers)) {
throw new TypeError('Illegal invocation')
}
if (args.length < 2) {
throw new TypeError(`Failed to execute 'append' on 'Headers': 2 arguments required, but only ${args.length} present.`)
}
const normalizedName = normalizeAndValidateHeaderName(args[0])
const normalizedName = normalizeAndValidateHeaderName(String(args[0]))

@@ -244,11 +231,14 @@ if (this[kGuard] === 'immutable') {

return this[kHeadersList].append(...args)
return this[kHeadersList].append(String(args[0]), String(args[1]))
}
delete (...args) {
if (!isHeaders(this)) {
throw new InvalidThisError('Header')
if (!(this instanceof Headers)) {
throw new TypeError('Illegal invocation')
}
if (args.length < 1) {
throw new TypeError(`Failed to execute 'delete' on 'Headers': 1 argument required, but only ${args.length} present.`)
}
const normalizedName = normalizeAndValidateHeaderName(args[0])
const normalizedName = normalizeAndValidateHeaderName(String(args[0]))

@@ -271,27 +261,36 @@ if (this[kGuard] === 'immutable') {

return this[kHeadersList].delete(...args)
return this[kHeadersList].delete(String(args[0]))
}
get (...args) {
if (!isHeaders(this)) {
throw new InvalidThisError('Header')
if (!(this instanceof Headers)) {
throw new TypeError('Illegal invocation')
}
if (args.length < 1) {
throw new TypeError(`Failed to execute 'get' on 'Headers': 1 argument required, but only ${args.length} present.`)
}
return this[kHeadersList].get(...args)
return this[kHeadersList].get(String(args[0]))
}
has (...args) {
if (!isHeaders(this)) {
throw new InvalidThisError('Header')
if (!(this instanceof Headers)) {
throw new TypeError('Illegal invocation')
}
if (args.length < 1) {
throw new TypeError(`Failed to execute 'has' on 'Headers': 1 argument required, but only ${args.length} present.`)
}
return this[kHeadersList].has(...args)
return this[kHeadersList].has(String(args[0]))
}
set (...args) {
if (!isHeaders(this)) {
throw new InvalidThisError('Header')
if (!(this instanceof Headers)) {
throw new TypeError('Illegal invocation')
}
if (args.length < 2) {
throw new TypeError(`Failed to execute 'set' on 'Headers': 2 arguments required, but only ${args.length} present.`)
}
const normalizedName = normalizeAndValidateHeaderName(args[0])
const normalizedName = normalizeAndValidateHeaderName(String(args[0]))

@@ -314,8 +313,8 @@ if (this[kGuard] === 'immutable') {

return this[kHeadersList].set(...args)
return this[kHeadersList].set(String(args[0]), String(args[1]))
}
* keys () {
if (!isHeaders(this)) {
throw new InvalidThisError('Headers')
if (!(this instanceof Headers)) {
throw new TypeError('Illegal invocation')
}

@@ -329,4 +328,4 @@

* values () {
if (!isHeaders(this)) {
throw new InvalidThisError('Headers')
if (!(this instanceof Headers)) {
throw new TypeError('Illegal invocation')
}

@@ -340,4 +339,4 @@

* entries () {
if (!isHeaders(this)) {
throw new InvalidThisError('Headers')
if (!(this instanceof Headers)) {
throw new TypeError('Illegal invocation')
}

@@ -350,6 +349,14 @@

forEach (callback, thisArg) {
if (!isHeaders(this)) {
throw new InvalidThisError('Headers')
forEach (...args) {
if (!(this instanceof Headers)) {
throw new TypeError('Illegal invocation')
}
if (args.length < 1) {
throw new TypeError(`Failed to execute 'forEach' on 'Headers': 1 argument required, but only ${args.length} present.`)
}
if (typeof args[0] !== 'function') {
throw new TypeError('Failed to execute \'forEach\' on \'Headers\': parameter 1 is not of type \'Function\'.')
}
const callback = args[0]
const thisArg = args[1]

@@ -367,2 +374,6 @@ for (let index = 0; index < this[kHeadersList].length; index += 2) {

[Symbol.for('nodejs.util.inspect.custom')] () {
if (!(this instanceof Headers)) {
throw new TypeError('Illegal invocation')
}
return this[kHeadersList]

@@ -369,0 +380,0 @@ }

@@ -15,12 +15,25 @@ // https://github.com/Ethan-Arrowood/undici-fetch

const {
ServiceWorkerGlobalScope,
Window,
matchRequestIntegrity,
makePolicyContainer,
clonePolicyContainer,
requestBadPort,
TAOCheck,
appendRequestOriginHeader,
responseLocationURL,
requestCurrentURL,
setRequestReferrerPolicyOnRedirect,
makeTimingInfo
tryUpgradeRequestToAPotentiallyTrustworthyURL,
makeTimingInfo,
appendFetchMetadata,
corsCheck,
crossOriginResourcePolicyCheck,
determineRequestsReferrer,
coarsenedSharedCurrentTime
} = require('./util')
const { kState, kHeaders, kGuard } = require('./symbols')
const { kState, kHeaders, kGuard, kRealm } = require('./symbols')
const { AbortError } = require('../core/errors')
const assert = require('assert')
const { safelyExtractBody } = require('./body')
const { safelyExtractBody, cancelBody } = require('./body')
const {

@@ -30,10 +43,11 @@ redirectStatus,

safeMethods,
requestBodyHeader
requestBodyHeader,
subresource
} = require('./constants')
const { kHeadersList } = require('../core/symbols')
const { ReadableStream } = require('stream/web')
const { performance } = require('perf_hooks')
const EE = require('events')
const { PassThrough, pipeline } = require('stream')
let ReadableStream
// https://fetch.spec.whatwg.org/#garbage-collection

@@ -45,3 +59,13 @@ const registry = new FinalizationRegistry((abort) => {

// https://fetch.spec.whatwg.org/#fetch-method
async function fetch (resource, init) {
async function fetch (...args) {
if (args.length < 1) {
throw new TypeError(`Failed to execute 'fetch' on 'Window': 1 argument required, but only ${args.length} present.`)
}
if (args.length >= 1 && typeof args[1] !== 'object' && args[1] !== undefined) {
throw new TypeError("Failed to execute 'fetch' on 'Window': cannot convert to dictionary.")
}
const resource = args[0]
const init = args.length >= 1 ? (args[1] ?? {}) : {}
const context = Object.assign(new EE(), {

@@ -89,7 +113,10 @@ dispatcher: this,

// 5. Let globalObject be request’s client’s global object.
// TODO
// TODO: What if request.client is null?
const globalObject = request.client?.globalObject
// 6. If globalObject is a ServiceWorkerGlobalScope object, then set
// request’s service-workers mode to "none".
// TODO
if (globalObject instanceof ServiceWorkerGlobalScope) {
request.serviceWorkers = 'none'
}

@@ -100,3 +127,3 @@ // 7. Let responseObject be null.

// 8. Let relevantRealm be this’s relevant Realm.
// TODO
const relevantRealm = null

@@ -145,5 +172,5 @@ // 9. Let locallyAborted be false.

if (response.status === 0) {
const error = new TypeError('fetch failed')
error.cause = response.error
p.reject(error)
p.reject(
Object.assign(new TypeError('fetch failed'), { cause: response.error })
)
return

@@ -154,7 +181,8 @@ }

// given response, "immutable", and relevantRealm.
// TODO: relevantRealm
responseObject = new Response()
responseObject[kState] = response
responseObject[kRealm] = relevantRealm
responseObject[kHeaders][kHeadersList] = response.headersList
responseObject[kHeaders][kGuard] = 'immutable'
responseObject[kHeaders][kRealm] = relevantRealm

@@ -165,7 +193,11 @@ // 5. Resolve p with responseObject.

fetching.call(context, {
request,
processResponseDone: handleFetchDone,
processResponse
})
fetching
.call(context, {
request,
processResponseDone: handleFetchDone,
processResponse
})
.catch((err) => {
p.reject(err)
})

@@ -178,3 +210,3 @@ // 13. Return p.

// 1. If response’s URL list is null or empty, then return.
if (response.urlList.length === 0) {
if (!response.urlList?.length) {
return

@@ -214,4 +246,4 @@ }

// TODO: given global’s relevant settings object’s cross-origin isolated
// capability
response.timingInfo.endTime = performance.now()
// capability?
response.timingInfo.endTime = coarsenedSharedCurrentTime()

@@ -250,3 +282,3 @@ // 8. Set response’s timing info to timingInfo.

if (request.body !== null) {
cancelIfReadable(request.body.stream, error)
cancelBody(request.body)
}

@@ -272,10 +304,18 @@

// 1. Let taskDestination be null.
// TODO
let taskDestination = null
// 2. Let crossOriginIsolatedCapability be false.
// TODO
let crossOriginIsolatedCapability = false
// 3. If request’s client is non-null, then:
// TODO
if (request.client !== null) {
// 1. Set taskDestination to request’s client’s global object.
taskDestination = request.client.globalObject
// 2. Set crossOriginIsolatedCapability to request’s client’s cross-origin
// isolated capability.
crossOriginIsolatedCapability =
request.client.crossOriginIsolatedCapability
}
// 4. If useParallelQueue is true, then set taskDestination to the result of

@@ -288,4 +328,3 @@ // starting a new parallel queue.

// crossOriginIsolatedCapability.
// TODO: Coarsened shared current time given crossOriginIsolatedCapability?
const currenTime = performance.now()
const currenTime = coarsenedSharedCurrentTime(crossOriginIsolatedCapability)
const timingInfo = makeTimingInfo({

@@ -310,3 +349,5 @@ startTime: currenTime,

processResponseEndOfBody: null,
processResponseDone
processResponseDone,
taskDestination,
crossOriginIsolatedCapability
}

@@ -316,3 +357,5 @@

// first return value of safely extracting request’s body.
// TODO
// NOTE: Since fetching is only called from fetch, body should already be
// extracted.
assert(!request.body || request.body.stream)

@@ -322,3 +365,9 @@ // 8. If request’s window is "client", then set request’s window to request’s

// "no-window".
// TODO
if (request.window === 'client') {
// TODO: What if request.client is null?
request.window =
request.client?.globalObject instanceof Window
? request.client
: 'no-window'
}

@@ -328,4 +377,4 @@ // 9. If request’s origin is "client", then set request’s origin to request’s

if (request.origin === 'client') {
// TODO: What is correct here?
request.origin = requestCurrentURL(request).origin
// TODO: What if request.client is null?
request.origin = request.client?.origin
}

@@ -335,3 +384,13 @@

if (request.policyContainer === 'client') {
// TODO
// 1. If request’s client is non-null, then set request’s policy
// container to a clone of request’s client’s policy container. [HTML]
if (request.client !== null) {
request.policyContainer = clonePolicyContainer(
request.client.policyContainer
)
} else {
// 2. Otherwise, set request’s policy container to a new policy
// container.
request.policyContainer = makePolicyContainer()
}
}

@@ -370,9 +429,18 @@

// user-agent-defined object.
// TODO
if (request.priority === null) {
// TODO
}
// 14. If request is a subresource request, then:
// TODO
if (subresource.includes(request.destination)) {
// 1. Let record be a new fetch record consisting of request and this
// instance of the fetch algorithm.
// TODO
// 2. Append record to request’s client’s fetch group list of fetch
// records.
// TODO
}
// 15. Run main fetch given fetchParams.
mainFetch.call(this, fetchParams)
return mainFetch.call(this, fetchParams)
}

@@ -391,3 +459,3 @@

// 3. If request’s local-URLs-only flag is set and request’s current URL is
// not local, then set response to a network error.
// not local, then set response to a network error.
if (

@@ -404,3 +472,3 @@ request.localURLsOnly &&

// 5. Upgrade request to a potentially trustworthy URL, if appropriate.
// TODO
tryUpgradeRequestToAPotentiallyTrustworthyURL(request)

@@ -419,3 +487,3 @@ // 6. If should request be blocked due to a bad port, should fetching request

if (request.referrerPolicy === '') {
// TODO
request.referrerPolicy = request.policyContainer.referrerPolicy
}

@@ -426,3 +494,3 @@

if (request.referrer !== 'no-referrer') {
// TODO
request.referrer = determineRequestsReferrer(request)
}

@@ -445,71 +513,72 @@

// the steps corresponding to the first matching statement:
// TODO
response = await (async () => {
// - request’s current URL’s origin is same origin with request’s origin,
// and request’s response tainting is "basic"
// - request’s current URL’s scheme is "data"
// - request’s mode is "navigate" or "websocket"
// 1. Set request’s response tainting to "basic".
// 2. Return the result of running scheme fetch given fetchParams.
// TODO
if (response === null) {
response = await (async () => {
// - request’s current URL’s origin is same origin with request’s origin,
// and request’s response tainting is "basic"
// - request’s current URL’s scheme is "data"
// - request’s mode is "navigate" or "websocket"
// 1. Set request’s response tainting to "basic".
// 2. Return the result of running scheme fetch given fetchParams.
// TODO
// request’s mode is "same-origin"
if (request.mode === 'same-origin') {
// 1. Return a network error.
return makeNetworkError('request mode cannot be "same-origin"')
}
// request’s mode is "no-cors"
if (request.mode === 'no-cors') {
// 1. If request’s redirect mode is not "follow", then return a network
// error.
if (request.redirect !== 'follow') {
return makeNetworkError(
'redirect cmode cannot be "follow" for "no-cors" request'
)
// request’s mode is "same-origin"
if (request.mode === 'same-origin') {
// 1. Return a network error.
return makeNetworkError('request mode cannot be "same-origin"')
}
// 2. Set request’s response tainting to "opaque".
request.responseTainting = 'opaque'
// request’s mode is "no-cors"
if (request.mode === 'no-cors') {
// 1. If request’s redirect mode is not "follow", then return a network
// error.
if (request.redirect !== 'follow') {
return makeNetworkError(
'redirect cmode cannot be "follow" for "no-cors" request'
)
}
// 3. Let noCorsResponse be the result of running scheme fetch given
// fetchParams.
// TODO
// 2. Set request’s response tainting to "opaque".
request.responseTainting = 'opaque'
// 4. If noCorsResponse is a filtered response or the CORB check with
// request and noCorsResponse returns allowed, then return noCorsResponse.
// TODO
// 3. Let noCorsResponse be the result of running scheme fetch given
// fetchParams.
// TODO
// 5. Return a new response whose status is noCorsResponse’s status.
// TODO
}
// 4. If noCorsResponse is a filtered response or the CORB check with
// request and noCorsResponse returns allowed, then return noCorsResponse.
// TODO
// request’s current URL’s scheme is not an HTTP(S) scheme
if (!/^https?:/.test(requestCurrentURL(request).protocol)) {
// Return a network error.
return makeNetworkError('URL scheme must be a HTTP(S) scheme')
}
// 5. Return a new response whose status is noCorsResponse’s status.
// TODO
}
// - request’s use-CORS-preflight flag is set
// - request’s unsafe-request flag is set and either request’s method is
// not a CORS-safelisted method or CORS-unsafe request-header names with
// request’s header list is not empty
// 1. Set request’s response tainting to "cors".
// 2. Let corsWithPreflightResponse be the result of running HTTP fetch
// given fetchParams and true.
// 3. If corsWithPreflightResponse is a network error, then clear cache
// entries using request.
// 4. Return corsWithPreflightResponse.
// TODO
// request’s current URL’s scheme is not an HTTP(S) scheme
if (!/^https?:/.test(requestCurrentURL(request).protocol)) {
// Return a network error.
return makeNetworkError('URL scheme must be a HTTP(S) scheme')
}
// Otherwise
// 1. Set request’s response tainting to "cors".
request.responseTainting = 'cors'
// - request’s use-CORS-preflight flag is set
// - request’s unsafe-request flag is set and either request’s method is
// not a CORS-safelisted method or CORS-unsafe request-header names with
// request’s header list is not empty
// 1. Set request’s response tainting to "cors".
// 2. Let corsWithPreflightResponse be the result of running HTTP fetch
// given fetchParams and true.
// 3. If corsWithPreflightResponse is a network error, then clear cache
// entries using request.
// 4. Return corsWithPreflightResponse.
// TODO
// 2. Return the result of running HTTP fetch given fetchParams.
return await httpFetch
.call(this, fetchParams)
.catch((err) => makeNetworkError(err))
})()
// Otherwise
// 1. Set request’s response tainting to "cors".
request.responseTainting = 'cors'
// 2. Return the result of running HTTP fetch given fetchParams.
return await httpFetch
.call(this, fetchParams)
.catch((err) => makeNetworkError(err))
})()
}
// 12. If recursive is true, then return response.

@@ -621,3 +690,6 @@ if (recursive) {

// then run processBodyError and abort these steps. [SRI]
// TODO
if (!matchRequestIntegrity(request, bytes)) {
processBodyError('integrity mismatch')
return
}

@@ -707,3 +779,5 @@ // 2. Set response’s body to the first return value of safely

// 5. If request’s service-workers mode is "all", then:
// TODO
if (request.serviceWorkers === 'all') {
// TODO
}

@@ -730,7 +804,14 @@ // 6. If response is null, then:

// for request and response returns failure, then return a network error.
// TODO
if (
request.responseTainting === 'cors' &&
corsCheck(request, response) === 'failure'
) {
return makeNetworkError('cors failure')
}
// 5. If the TAO check for request and response returns failure, then set
// request’s timing allow failed flag.
// TODO
if (TAOCheck(request, response) === 'failure') {
request.timingAllowFailed = true
}
}

@@ -742,3 +823,13 @@

// and actualResponse returns blocked, then return a network error.
// TODO
if (
(request.responseTainting === 'opaque' || response.type === 'opaque') &&
crossOriginResourcePolicyCheck(
request.origin,
request.client,
request.destination,
actualResponse
) === 'blocked'
) {
return makeNetworkError('blocked')
}

@@ -760,3 +851,3 @@ // 8. If actualResponse’s status is a redirect status, then:

// response is actualResponse.
response = filterResponse(response, 'opaqueredirect')
response = filterResponse(actualResponse, 'opaqueredirect')
} else if (request.redirect === 'follow') {

@@ -810,3 +901,3 @@ // Set response to the result of running HTTP-redirect fetch given

// error.
if (!/^https?:/.test(locationURL)) {
if (!/^https?:/.test(locationURL.protocol)) {
return makeNetworkError('URL scheme must be a HTTP(S) scheme')

@@ -826,3 +917,7 @@ }

// a network error.
if (request.mode === 'cors' && request.origin !== locationURL.origin) {
if (
request.mode === 'cors' &&
(locationURL.username || locationURL.password) &&
request.origin !== locationURL.origin
) {
return makeNetworkError('cross origin not allowed for request mode "cors"')

@@ -876,3 +971,3 @@ }

// 2. For each headerName of request-body-header name, delete headerName from
// request’s header list.
// request’s header list.
for (const headerName of requestBodyHeader) {

@@ -896,5 +991,4 @@ request.headersList.delete(headerName)

// capability.
// TODO: given fetchParams’s cross-origin isolated capability?
timingInfo.redirectEndTime = timingInfo.postRedirectStartTime =
performance.now()
coarsenedSharedCurrentTime(fetchParams.crossOriginIsolatedCapability)

@@ -939,3 +1033,3 @@ // 17. If timingInfo’s redirect start time is 0, then set timingInfo’s

// 5. Let storedResponse be null.
// TODO
// TODO: cache

@@ -1020,30 +1114,7 @@ // 6. Let httpCache be null.

// 11. Append a request `Origin` header for httpRequest.
// TODO
appendRequestOriginHeader(httpRequest)
// 12. Append the Fetch metadata headers for httpRequest. [FETCH-METADATA]
appendFetchMetadata(httpRequest)
// https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-dest-header
// TODO
// https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-mode-header
{
// 1. Assert: r’s url is a potentially trustworthy URL.
// TODO
// 2. Let header be a Structured Header whose value is a token.
let header = null
// 3. Set header’s value to r’s mode.
header = request.mode
// 4. Set a structured field value `Sec-Fetch-Mode`/header in r’s header list.
httpRequest.headersList.append('sec-fetch-mode', header)
}
// https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-site-header
// TODO
// https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-user-header
// TODO
// 13. If httpRequest’s header list does not contain `User-Agent`, then

@@ -1107,2 +1178,9 @@ // user agents should append `User-Agent`/default `User-Agent` value to

// TODO: https://github.com/whatwg/fetch/issues/1285#issuecomment-896560129
if (!httpRequest.headersList.has('accept-encoding')) {
if (/^https:/.test(requestCurrentURL(httpRequest).protocol)) {
httpRequest.headersList.append('accept-encoding', 'br, gzip, deflate')
} else {
httpRequest.headersList.append('accept-encoding', 'gzip, deflate')
}
}

@@ -1113,13 +1191,13 @@ // 19. If includeCredentials is true, then:

// (see section 7 of [COOKIES]), then:
// TODO
// TODO: credentials
// 2. If httpRequest’s header list does not contain `Authorization`, then:
// TODO
// TODO: credentials
}
// 20. If there’s a proxy-authentication entry, use it as appropriate.
// TODO
// TODO: proxy-authentication
// 21. Set httpCache to the result of determining the HTTP cache
// partition, given httpRequest.
// TODO
// TODO: cache

@@ -1135,3 +1213,3 @@ // 22. If httpCache is null, then set httpRequest’s cache mode to

if (httpRequest.mode !== 'no-store' && httpRequest.mode !== 'reload') {
// TODO
// TODO: cache
}

@@ -1168,3 +1246,3 @@

) {
// TODO
// TODO: cache
}

@@ -1175,3 +1253,3 @@

if (revalidatingFlag && forwardResponse.status === 304) {
// TODO
// TODO: cache
}

@@ -1186,3 +1264,3 @@

// "Storing Responses in Caches" chapter of HTTP Caching. [HTTP-CACHING]
// TODO
// TODO: cache
}

@@ -1274,3 +1352,2 @@ }

// 16. If isAuthenticationFetch is true, then create an authentication entry
// for request and the given realm.
if (isAuthenticationFetch) {

@@ -1342,3 +1419,3 @@ // TODO

// given request.
// TODO
// TODO: cache
const httpCache = null

@@ -1356,3 +1433,12 @@

// 7. Switch on request’s mode:
// TODO
if (request.mode === 'websocket') {
// Let connection be the result of obtaining a WebSocket connection,
// given request’s current URL.
// TODO
} else {
// Let connection be the result of obtaining a connection, given
// networkPartitionKey, request’s current URL’s origin,
// includeCredentials, and forceNewConnection.
// TODO
}

@@ -1492,2 +1578,6 @@ // 8. Run these steps, but abort when the ongoing fetch is terminated:

// highWaterMark, and sizeAlgorithm set to sizeAlgorithm.
if (!ReadableStream) {
ReadableStream = require('stream/web').ReadableStream
}
const stream = new ReadableStream(

@@ -1625,3 +1715,4 @@ {

} else {
// TODO: What to do when coding is invalid or unsupported?
decoders.length = 0
break
}

@@ -1775,13 +1866,2 @@ }

function cancelIfReadable (stream, reason) {
try {
stream.cancel(reason)
} catch (err) {
// Will throw TypeError if body is not readable.
if (err.name !== 'TypeError') {
throw err
}
}
}
module.exports = fetch

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

const util = require('../core/util')
const { isValidHTTPToken } = require('./util')
const { isValidHTTPToken, EnvironmentSettingsObject } = require('./util')
const {

@@ -20,3 +20,3 @@ forbiddenMethods,

const { kEnumerableProperty } = util
const { kHeaders, kSignal, kState, kGuard } = require('./symbols')
const { kHeaders, kSignal, kState, kGuard, kRealm } = require('./symbols')
const { kHeadersList } = require('../core/symbols')

@@ -27,10 +27,24 @@ const assert = require('assert')

const kInit = Symbol('init')
// https://fetch.spec.whatwg.org/#request-class
class Request {
// https://fetch.spec.whatwg.org/#dom-request
constructor (input, init = {}) {
if (!(input instanceof Request)) {
input = String(input)
constructor (...args) {
if (args[0] === kInit) {
return
}
if (args.length < 1) {
throw new TypeError(`Failed to construct 'Request': 1 argument required, but only ${args.length} present.`)
}
if (args.length >= 1 && typeof args[1] !== 'object' && args[1] !== undefined) {
throw new TypeError("Failed to construct 'Request': cannot convert to dictionary.")
}
const input = args[0] instanceof Request ? args[0] : String(args[0])
const init = args.length >= 1 ? (args[1] ?? {}) : {}
// TODO
this[kRealm] = { settingsObject: {} }
// 1. Let request be null.

@@ -43,4 +57,3 @@ let request = null

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

@@ -90,3 +103,3 @@ // 4. Let signal be null.

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

@@ -98,3 +111,8 @@ // 8. Let window be "client".

// is same origin with origin, then set window to request’s window.
// TODO
if (
request.window instanceof EnvironmentSettingsObject &&
request.window.origin === origin
) {
window = request.window
}

@@ -112,3 +130,6 @@ // 10. If init["window"] exists and is non-null, then throw a TypeError.

// 12. Set request to a new request with the following properties:
request = makeRequest({ ...request, window })
request = makeRequest({
...request,
window
})

@@ -286,5 +307,5 @@ // 13. If init is not empty, then:

// Realm.
// TODO: relevant Realm?
const ac = new AbortController()
this[kSignal] = ac.signal
this[kSignal][kRealm] = this[kRealm]

@@ -320,6 +341,6 @@ // 29. If signal is not null, then make this’s signal follow signal.

// "request".
// TODO: relevant Realm?
this[kHeaders] = new Headers()
this[kHeaders][kGuard] = 'request'
this[kHeaders][kHeadersList] = request.headersList
this[kHeaders][kRealm] = this[kRealm]

@@ -452,2 +473,6 @@ // 31. If this’s request’s mode is "no-cors", then:

get [Symbol.toStringTag] () {
if (!(this instanceof Request)) {
throw new TypeError('Illegal invocation')
}
return this.constructor.name

@@ -458,2 +483,6 @@ }

get method () {
if (!(this instanceof Request)) {
throw new TypeError('Illegal invocation')
}
// The method getter steps are to return this’s request’s method.

@@ -465,2 +494,6 @@ return this[kState].method

get url () {
if (!(this instanceof Request)) {
throw new TypeError('Illegal invocation')
}
// The url getter steps are to return this’s request’s URL, serialized.

@@ -474,2 +507,6 @@ return this[kState].url.toString()

get headers () {
if (!(this instanceof Request)) {
throw new TypeError('Illegal invocation')
}
// The headers getter steps are to return this’s headers.

@@ -482,4 +519,8 @@ return this[kHeaders]

get destination () {
if (!(this instanceof Request)) {
throw new TypeError('Illegal invocation')
}
// The destination getter are to return this’s request’s destination.
return ''
return this[kState].destination
}

@@ -493,2 +534,6 @@

get referrer () {
if (!(this instanceof Request)) {
throw new TypeError('Illegal invocation')
}
// 1. If this’s request’s referrer is "no-referrer", then return the

@@ -514,2 +559,6 @@ // empty string.

get referrerPolicy () {
if (!(this instanceof Request)) {
throw new TypeError('Illegal invocation')
}
// The referrerPolicy getter steps are to return this’s request’s referrer policy.

@@ -523,2 +572,6 @@ return this[kState].referrerPolicy

get mode () {
if (!(this instanceof Request)) {
throw new TypeError('Illegal invocation')
}
// The mode getter steps are to return this’s request’s mode.

@@ -540,2 +593,6 @@ return this[kState].mode

get cache () {
if (!(this instanceof Request)) {
throw new TypeError('Illegal invocation')
}
// The cache getter steps are to return this’s request’s cache mode.

@@ -550,2 +607,6 @@ return this[kState].cache

get redirect () {
if (!(this instanceof Request)) {
throw new TypeError('Illegal invocation')
}
// The redirect getter steps are to return this’s request’s redirect mode.

@@ -559,2 +620,6 @@ return this[kState].redirect

get integrity () {
if (!(this instanceof Request)) {
throw new TypeError('Illegal invocation')
}
// The integrity getter steps are to return this’s request’s integrity

@@ -568,2 +633,6 @@ // metadata.

get keepalive () {
if (!(this instanceof Request)) {
throw new TypeError('Illegal invocation')
}
// The keepalive getter steps are to return this’s request’s keepalive.

@@ -576,2 +645,6 @@ return this[kState].keepalive

get isReloadNavigation () {
if (!(this instanceof Request)) {
throw new TypeError('Illegal invocation')
}
// The isReloadNavigation getter steps are to return true if this’s

@@ -585,2 +658,6 @@ // request’s reload-navigation flag is set; otherwise false.

get isHistoryNavigation () {
if (!(this instanceof Request)) {
throw new TypeError('Illegal invocation')
}
// The isHistoryNavigation getter steps are to return true if this’s request’s

@@ -595,2 +672,6 @@ // history-navigation flag is set; otherwise false.

get signal () {
if (!(this instanceof Request)) {
throw new TypeError('Illegal invocation')
}
// The signal getter steps are to return this’s signal.

@@ -602,2 +683,6 @@ return this[kSignal]

clone () {
if (!(this instanceof Request)) {
throw new TypeError('Illegal invocation')
}
// 1. If this is unusable, then throw a TypeError.

@@ -613,7 +698,9 @@ if (this.bodyUsed || (this.body && this.body.locked)) {

// given clonedRequest, this’s headers’s guard, and this’s relevant Realm.
// TODO: relevant Realm?
const clonedRequestObject = new Request()
const clonedRequestObject = new Request(kInit)
clonedRequestObject[kState] = clonedRequest
clonedRequestObject[kRealm] = this[kRealm]
clonedRequestObject[kHeaders] = new Headers()
clonedRequestObject[kHeaders][kHeadersList] = clonedRequest.headersList
clonedRequestObject[kHeaders][kGuard] = this[kHeaders][kGuard]
clonedRequestObject[kHeaders][kRealm] = this[kHeaders][kRealm]

@@ -620,0 +707,0 @@ // 4. Make clonedRequestObject’s signal follow this’s signal.

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

} = require('./constants')
const { kState, kHeaders, kGuard } = require('./symbols')
const { kState, kHeaders, kGuard, kRealm } = require('./symbols')
const { kHeadersList } = require('../core/symbols')

@@ -22,10 +22,14 @@ const assert = require('assert')

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.
// TODO: relevant Realm?
const responseObject = new Response()
responseObject[kState] = makeNetworkError()
responseObject[kRealm] = relevantRealm
responseObject[kHeaders][kHeadersList] = responseObject[kState].headersList
responseObject[kHeaders][kGuard] = 'immutable'
responseObject[kHeaders][kRealm] = relevantRealm
return responseObject

@@ -35,3 +39,12 @@ }

// Creates a redirect Response that redirects to url with status status.
static redirect (url, status = 302) {
static redirect (...args) {
const relevantRealm = { settingsObject: {} }
if (args.length < 1) {
throw new TypeError(`Failed to execute 'redirect' on 'Response': 1 argument required, but only ${args.length} present.`)
}
const status = args.length >= 2 ? args[1] : 302
const url = String(args[0])
// 1. Let parsedURL be the result of parsing url with current settings

@@ -45,5 +58,3 @@ // object’s API base URL.

} catch (err) {
const error = new TypeError('Failed to parse URL from ' + url)
error.cause = err
throw error
throw Object.assign(new TypeError('Failed to parse URL from ' + url), { cause: err })
}

@@ -58,5 +69,6 @@

// given a new response, "immutable", and this’s relevant Realm.
// TODO: relevant Realm?
const responseObject = new Response()
responseObject[kRealm] = relevantRealm
responseObject[kHeaders][kGuard] = 'immutable'
responseObject[kHeaders][kRealm] = relevantRealm

@@ -78,3 +90,13 @@ // 5. Set responseObject’s response’s status to status.

// https://fetch.spec.whatwg.org/#dom-response
constructor (body = null, init = {}) {
constructor (...args) {
if (args.length >= 1 && typeof args[1] !== 'object' && args[1] !== undefined) {
throw new TypeError("Failed to construct 'Request': cannot convert to dictionary.")
}
const body = args.length >= 1 ? args[0] : null
const init = args.length >= 2 ? (args[1] ?? {}) : {}
// TODO
this[kRealm] = { settingsObject: {} }
// 1. If init["status"] is not in the range 200 to 599, inclusive, then

@@ -110,6 +132,6 @@ // throw a RangeError.

// is "response".
// TODO: relevant Realm?
this[kHeaders] = new Headers()
this[kHeaders][kGuard] = 'response'
this[kHeaders][kHeadersList] = this[kState].headersList
this[kHeaders][kRealm] = this[kRealm]

@@ -154,2 +176,6 @@ // 5. Set this’s response’s status to init["status"].

get [Symbol.toStringTag] () {
if (!(this instanceof Response)) {
throw new TypeError('Illegal invocation')
}
return this.constructor.name

@@ -160,2 +186,6 @@ }

get type () {
if (!(this instanceof Response)) {
throw new TypeError('Illegal invocation')
}
// The type getter steps are to return this’s response’s type.

@@ -167,2 +197,6 @@ return this[kState].type

get url () {
if (!(this instanceof Response)) {
throw new TypeError('Illegal invocation')
}
// The url getter steps are to return the empty string if this’s

@@ -187,2 +221,6 @@ // response’s URL is null; otherwise this’s response’s URL,

get redirected () {
if (!(this instanceof Response)) {
throw new TypeError('Illegal invocation')
}
// The redirected getter steps are to return true if this’s response’s URL

@@ -195,2 +233,6 @@ // list has more than one item; otherwise false.

get status () {
if (!(this instanceof Response)) {
throw new TypeError('Illegal invocation')
}
// The status getter steps are to return this’s response’s status.

@@ -202,2 +244,6 @@ return this[kState].status

get ok () {
if (!(this instanceof Response)) {
throw new TypeError('Illegal invocation')
}
// The ok getter steps are to return true if this’s response’s status is an

@@ -210,2 +256,6 @@ // ok status; otherwise false.

get statusText () {
if (!(this instanceof Response)) {
throw new TypeError('Illegal invocation')
}
// The statusText getter steps are to return this’s response’s status

@@ -218,2 +268,6 @@ // message.

get headers () {
if (!(this instanceof Response)) {
throw new TypeError('Illegal invocation')
}
// The headers getter steps are to return this’s headers.

@@ -225,2 +279,6 @@ return this[kHeaders]

clone () {
if (!(this instanceof Response)) {
throw new TypeError('Illegal invocation')
}
// 1. If this is unusable, then throw a TypeError.

@@ -236,7 +294,8 @@ if (this.bodyUsed || (this.body && this.body.locked)) {

// clonedResponse, this’s headers’s guard, and this’s relevant Realm.
// TODO: relevant Realm?
const clonedResponseObject = new Response()
clonedResponseObject[kState] = clonedResponse
clonedResponseObject[kRealm] = this[kRealm]
clonedResponseObject[kHeaders][kHeadersList] = clonedResponse.headersList
clonedResponseObject[kHeaders][kGuard] = this[kHeaders][kGuard]
clonedResponseObject[kHeaders][kRealm] = this[kHeaders][kRealm]

@@ -243,0 +302,0 @@ return clonedResponseObject

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

kState: Symbol('state'),
kGuard: Symbol('guard')
kGuard: Symbol('guard'),
kRealm: Symbol('realm')
}

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

const { finished } = require('stream')
const { performance } = require('perf_hooks')

@@ -182,3 +183,7 @@ let ReadableStream

} else {
controller.close()
queueMicrotask(() => {
// Must not use `process.nextTick()`.
// See https://github.com/nodejs/node/issues/39758
controller.close()
})
}

@@ -224,2 +229,55 @@ })

// https://fetch.spec.whatwg.org/#cross-origin-resource-policy-check
function crossOriginResourcePolicyCheck () {
// TODO
return 'allowed'
}
// https://fetch.spec.whatwg.org/#concept-cors-check
function corsCheck () {
// TODO
return 'success'
}
// https://fetch.spec.whatwg.org/#concept-tao-check
function TAOCheck () {
// TODO
return 'success'
}
function appendFetchMetadata (httpRequest) {
// https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-dest-header
// TODO
// https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-mode-header
// 1. Assert: r’s url is a potentially trustworthy URL.
// TODO
// 2. Let header be a Structured Header whose value is a token.
let header = null
// 3. Set header’s value to r’s mode.
header = httpRequest.mode
// 4. Set a structured field value `Sec-Fetch-Mode`/header in r’s header list.
httpRequest.headersList.append('sec-fetch-mode', header)
// https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-site-header
// TODO
// https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-user-header
// TODO
}
// https://fetch.spec.whatwg.org/#append-a-request-origin-header
function appendRequestOriginHeader (request) {
// TODO
}
function coarsenedSharedCurrentTime (crossOriginIsolatedCapability) {
// TODO
return performance.now()
}
function makeTimingInfo (init) {

@@ -242,3 +300,48 @@ return {

// https://html.spec.whatwg.org/multipage/origin.html#policy-container
function makePolicyContainer () {
// TODO
return {}
}
// https://html.spec.whatwg.org/multipage/origin.html#clone-a-policy-container
function clonePolicyContainer () {
// TODO
return {}
}
// https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer
function determineRequestsReferrer (request) {
// TODO
return 'no-referrer'
}
function matchRequestIntegrity (request, bytes) {
return false
}
// https://w3c.github.io/webappsec-upgrade-insecure-requests/#upgrade-request
function tryUpgradeRequestToAPotentiallyTrustworthyURL (request) {
// TODO
}
class ServiceWorkerGlobalScope {} // dummy
class Window {} // dummy
class EnvironmentSettingsObject {} // dummy
module.exports = {
ServiceWorkerGlobalScope,
Window,
EnvironmentSettingsObject,
tryUpgradeRequestToAPotentiallyTrustworthyURL,
coarsenedSharedCurrentTime,
matchRequestIntegrity,
determineRequestsReferrer,
makePolicyContainer,
clonePolicyContainer,
appendFetchMetadata,
appendRequestOriginHeader,
TAOCheck,
corsCheck,
crossOriginResourcePolicyCheck,
toWebReadable,

@@ -245,0 +348,0 @@ makeTimingInfo,

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

const { InvalidArgumentError } = require('../core/errors')
const EE = require('events')

@@ -55,4 +56,3 @@ const redirectableStatusCodes = [300, 301, 302, 303, 307, 308]

this.opts.body[kBodyUsed] = false
// TODO (fix): Don't mutate readable state...
this.opts.body.on('data', function () {
EE.prototype.on.call(this.opts.body, 'data', function () {
this[kBodyUsed] = true

@@ -59,0 +59,0 @@ })

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

@@ -36,10 +36,10 @@ "homepage": "https://undici.nodejs.org",

"lint:fix": "standard --fix | snazzy",
"test": "tap test/*.js --no-coverage && mocha test/node-fetch && jest test/jest/test",
"test": "npm run test:tap && npm run test:node-fetch && npm run test:jest",
"test:node-fetch": "node scripts/test-node-fetch.js 16 && mocha test/node-fetch || echo Skipping",
"test:jest": "jest test/jest/test",
"test:tap": "tap test/*.js --no-coverage ",
"test:tdd": "tap test/*.js -w --no-coverage-report",
"test:tap": "tap test/*.js",
"test:tdd": "tap test/*.js -w",
"test:typescript": "tsd",
"coverage": "standard | snazzy && tap test/*.js",
"coverage:ci": "npm run coverage -- --coverage-report=lcovonly",
"coverage": "nyc npm run test",
"coverage:ci": "npm run coverage -- --reporter=lcovonly",
"bench": "concurrently -k -s first npm:bench:server npm:bench:run",

@@ -95,2 +95,5 @@ "bench:server": "node benchmarks/server.js",

},
"tap": {
"check-coverage": false
},
"tsd": {

@@ -97,0 +100,0 @@ "directory": "test/types",

@@ -94,3 +94,3 @@ # undici

* **url** `string | URL | object`
* **url** `string | URL | UrlObject`
* **options** [`RequestOptions`](./docs/api/Dispatcher.md#parameter-requestoptions)

@@ -111,3 +111,3 @@ * **dispatcher** `Dispatcher` - Default: [getGlobalDispatcher](#undicigetglobaldispatcherdispatcher)

* **url** `string | URL | object`
* **url** `string | URL | UrlObject`
* **options** [`StreamOptions`](./docs/api/Dispatcher.md#parameter-streamoptions)

@@ -129,3 +129,3 @@ * **dispatcher** `Dispatcher` - Default: [getGlobalDispatcher](#undicigetglobaldispatcherdispatcher)

* **url** `string | URL | object`
* **url** `string | URL | UrlObject`
* **options** [`PipelineOptions`](docs/api/Dispatcher.md#parameter-pipelineoptions)

@@ -149,3 +149,3 @@ * **dispatcher** `Dispatcher` - Default: [getGlobalDispatcher](#undicigetglobaldispatcherdispatcher)

* **url** `string | URL | object`
* **url** `string | URL | UrlObject`
* **options** [`ConnectOptions`](docs/api/Dispatcher.md#parameter-connectoptions)

@@ -166,8 +166,8 @@ * **dispatcher** `Dispatcher` - Default: [getGlobalDispatcher](#undicigetglobaldispatcherdispatcher)

https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch
https://fetch.spec.whatwg.org/#fetch-method
* https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch
* https://fetch.spec.whatwg.org/#fetch-method
Only supported on Node 16+.
This is [experimental](https://nodejs.org/api/documentation.html#documentation_stability_index) and is not yet fully compliant the Fetch Standard. We plan to ship breaking changes to this feature until it is out of experimental.
This is [experimental](https://nodejs.org/api/documentation.html#documentation_stability_index) and is not yet fully compliant with the Fetch Standard. We plan to ship breaking changes to this feature until it is out of experimental.

@@ -180,3 +180,3 @@ ### `undici.upgrade([url, options]): Promise`

* **url** `string | URL | object`
* **url** `string | URL | UrlObject`
* **options** [`UpgradeOptions`](docs/api/Dispatcher.md#parameter-upgradeoptions)

@@ -205,2 +205,12 @@ * **dispatcher** `Dispatcher` - Default: [getGlobalDispatcher](#undicigetglobaldispatcherdispatcher)

### `UrlObject`
* **port** `string | number` (optional)
* **path** `string` (optional)
* **pathname** `string` (optional)
* **hostname** `string` (optional)
* **origin** `string` (optional)
* **protocol** `string` (optional)
* **search** `string` (optional)
## Specification Compliance

@@ -207,0 +217,0 @@

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