Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNode.js GitHub Bot <github-bot@iojs.org>2022-05-25 01:23:21 +0300
committerGitHub <noreply@github.com>2022-05-25 01:23:21 +0300
commit810893f145dbba6bfc823afbc5958505378ba963 (patch)
tree2d58997a79002162bc69d829f0bfb0d84cadbf61
parent4a3ba87eabd7bbceb95f0e902fa37a76c0aff223 (diff)
deps: update undici to 5.3.0
PR-URL: https://github.com/nodejs/node/pull/43197 Reviewed-By: Darshan Sen <raisinten@gmail.com> Reviewed-By: Robert Nagy <ronagy@icloud.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Mohammed Keyvanzadeh <mohammadkeyvanzade94@gmail.com> Reviewed-By: Tobias Nießen <tniessen@tnie.de> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
-rw-r--r--deps/undici/src/README.md3
-rw-r--r--deps/undici/src/docs/api/Dispatcher.md4
-rw-r--r--deps/undici/src/docs/best-practices/mocking-request.md32
-rw-r--r--deps/undici/src/index.d.ts1
-rw-r--r--deps/undici/src/lib/api/api-request.js15
-rw-r--r--deps/undici/src/lib/core/errors.js14
-rw-r--r--deps/undici/src/lib/core/request.js10
-rw-r--r--deps/undici/src/lib/core/util.js48
-rw-r--r--deps/undici/src/lib/fetch/file.js8
-rw-r--r--deps/undici/src/lib/fetch/formdata.js8
-rw-r--r--deps/undici/src/lib/fetch/index.js18
-rw-r--r--deps/undici/src/lib/fetch/request.js4
-rw-r--r--deps/undici/src/lib/fetch/response.js169
-rw-r--r--deps/undici/src/lib/fetch/util.js63
-rw-r--r--deps/undici/src/lib/mock/mock-agent.js6
-rw-r--r--deps/undici/src/lib/mock/mock-utils.js3
-rw-r--r--deps/undici/src/lib/proxy-agent.js1
-rw-r--r--deps/undici/src/package.json5
-rw-r--r--deps/undici/src/types/diagnostics-channel.d.ts66
-rw-r--r--deps/undici/src/types/dispatcher.d.ts4
-rw-r--r--deps/undici/src/types/fetch.d.ts27
-rw-r--r--deps/undici/undici.js262
22 files changed, 487 insertions, 284 deletions
diff --git a/deps/undici/src/README.md b/deps/undici/src/README.md
index 5acff95e270..b7a5ef1acd4 100644
--- a/deps/undici/src/README.md
+++ b/deps/undici/src/README.md
@@ -198,7 +198,7 @@ You can pass an optional dispatcher to `fetch` as:
```js
import { fetch, Agent } from 'undici'
-
+
const res = await fetch('https://example.com', {
// Mocks are also supported
dispatcher: new Agent({
@@ -375,6 +375,7 @@ Refs: https://fetch.spec.whatwg.org/#atomic-http-redirect-handling
* [__Daniele Belardi__](https://github.com/dnlup), <https://www.npmjs.com/~dnlup>
* [__Ethan Arrowood__](https://github.com/ethan-arrowood), <https://www.npmjs.com/~ethan_arrowood>
* [__Matteo Collina__](https://github.com/mcollina), <https://www.npmjs.com/~matteo.collina>
+* [__Matthew Aitken__](https://github.com/KhafraDev), <https://www.npmjs.com/~khaf>
* [__Robert Nagy__](https://github.com/ronag), <https://www.npmjs.com/~ronag>
* [__Szymon Marczak__](https://github.com/szmarczak), <https://www.npmjs.com/~szmarczak>
* [__Tomas Della Vedova__](https://github.com/delvedor), <https://www.npmjs.com/~delvedor>
diff --git a/deps/undici/src/docs/api/Dispatcher.md b/deps/undici/src/docs/api/Dispatcher.md
index 56b34275209..ffe72cceb1b 100644
--- a/deps/undici/src/docs/api/Dispatcher.md
+++ b/deps/undici/src/docs/api/Dispatcher.md
@@ -194,18 +194,20 @@ Returns: `Boolean` - `false` if dispatcher is busy and further dispatch calls wo
* **method** `string`
* **body** `string | Buffer | Uint8Array | stream.Readable | Iterable | AsyncIterable | null` (optional) - Default: `null`
* **headers** `UndiciHeaders | string[]` (optional) - Default: `null`.
+* **query** `Record<string, any> | null` (optional) - Default: `null` - Query string params to be embedded in the request URL. Note that both keys and values of query are encoded using `encodeURIComponent`. If for some reason you need to send them unencoded, embed query params into path directly instead.
* **idempotent** `boolean` (optional) - Default: `true` if `method` is `'HEAD'` or `'GET'` - Whether the requests can be safely retried or not. If `false` the request won't be sent until all preceding requests in the pipeline has completed.
* **blocking** `boolean` (optional) - Default: `false` - Whether the response is expected to take a long time and would end up blocking the pipeline. When this is set to `true` further pipelining will be avoided on the same connection until headers have been received.
* **upgrade** `string | null` (optional) - Default: `null` - Upgrade the request. Should be used to specify the kind of upgrade i.e. `'Websocket'`.
* **bodyTimeout** `number | null` (optional) - The timeout after which a request will time out, in milliseconds. Monitors time between receiving body data. Use `0` to disable it entirely. Defaults to 30 seconds.
* **headersTimeout** `number | null` (optional) - The amount of time the parser will wait to receive the complete HTTP headers. Defaults to 30 seconds.
+* **throwOnError** `boolean` (optional) - Default: `false` - Whether Undici should throw an error upon receiving a 4xx or 5xx response from the server.
#### Parameter: `DispatchHandler`
* **onConnect** `(abort: () => void, context: object) => void` - 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.
* **onError** `(error: Error) => void` - Invoked when an error has occurred. May not throw.
* **onUpgrade** `(statusCode: number, headers: Buffer[], socket: Duplex) => void` (optional) - Invoked when request is upgraded. Required if `DispatchOptions.upgrade` is defined or `DispatchOptions.method === 'CONNECT'`.
-* **onHeaders** `(statusCode: number, headers: Buffer[], resume: () => void) => boolean` - Invoked when statusCode and headers have been received. May be invoked multiple times due to 1xx informational headers. Not required for `upgrade` requests.
+* **onHeaders** `(statusCode: number, headers: Buffer[], resume: () => void, statusText: string) => boolean` - Invoked when statusCode and headers have been received. May be invoked multiple times due to 1xx informational headers. Not required for `upgrade` requests.
* **onData** `(chunk: Buffer) => boolean` - Invoked when response payload data is received. Not required for `upgrade` requests.
* **onComplete** `(trailers: Buffer[]) => void` - Invoked when response payload and trailers have been received and the request has completed. Not required for `upgrade` requests.
* **onBodySent** `(chunk: string | Buffer | Uint8Array) => void` - Invoked when a body chunk is sent to the server. Not required. For a stream or iterable body this will be invoked for every chunk. For other body types, it will be invoked once after the body is sent.
diff --git a/deps/undici/src/docs/best-practices/mocking-request.md b/deps/undici/src/docs/best-practices/mocking-request.md
index ebcc90d24b7..b98a450a32e 100644
--- a/deps/undici/src/docs/best-practices/mocking-request.md
+++ b/deps/undici/src/docs/best-practices/mocking-request.md
@@ -101,4 +101,36 @@ const badRequest = await bankTransfer('1234567890', '100')
// subsequent request to origin http://localhost:3000 was not allowed (net.connect disabled)
```
+## Reply with data based on request
+If the mocked response needs to be dynamically derived from the request parameters, you can provide a function instead of an object to `reply`
+
+```js
+mockPool.intercept({
+ path: '/bank-transfer',
+ method: 'POST',
+ headers: {
+ 'X-TOKEN-SECRET': 'SuperSecretToken',
+ },
+ body: JSON.stringify({
+ recepient: '1234567890',
+ amount: '100'
+ })
+}).reply(200, (opts) => {
+ // do something with opts
+
+ return { message: 'transaction processed' }
+})
+```
+
+in this case opts will be
+
+```
+{
+ method: 'POST',
+ headers: { 'X-TOKEN-SECRET': 'SuperSecretToken' },
+ body: '{"recepient":"1234567890","amount":"100"}',
+ origin: 'http://localhost:3000',
+ path: '/bank-transfer'
+}
+```
diff --git a/deps/undici/src/index.d.ts b/deps/undici/src/index.d.ts
index 44ab285041f..e4aa8f62cdb 100644
--- a/deps/undici/src/index.d.ts
+++ b/deps/undici/src/index.d.ts
@@ -16,6 +16,7 @@ import { request, pipeline, stream, connect, upgrade } from './types/api'
export * from './types/fetch'
export * from './types/file'
export * from './types/formdata'
+export * from './types/diagnostics-channel'
export { Interceptable } from './types/mock-interceptor'
export { Dispatcher, BalancedPool, Pool, Client, buildConnector, errors, Agent, request, stream, pipeline, connect, upgrade, setGlobalDispatcher, getGlobalDispatcher, MockClient, MockPool, MockAgent, mockErrors, ProxyAgent }
diff --git a/deps/undici/src/lib/api/api-request.js b/deps/undici/src/lib/api/api-request.js
index bcfe483ebef..2fc5afa991c 100644
--- a/deps/undici/src/lib/api/api-request.js
+++ b/deps/undici/src/lib/api/api-request.js
@@ -3,7 +3,8 @@
const Readable = require('./readable')
const {
InvalidArgumentError,
- RequestAbortedError
+ RequestAbortedError,
+ ResponseStatusCodeError
} = require('../core/errors')
const util = require('../core/util')
const { AsyncResource } = require('async_hooks')
@@ -15,7 +16,7 @@ class RequestHandler extends AsyncResource {
throw new InvalidArgumentError('invalid opts')
}
- const { signal, method, opaque, body, onInfo, responseHeaders } = opts
+ const { signal, method, opaque, body, onInfo, responseHeaders, throwOnError } = opts
try {
if (typeof callback !== 'function') {
@@ -51,6 +52,7 @@ class RequestHandler extends AsyncResource {
this.trailers = {}
this.context = null
this.onInfo = onInfo || null
+ this.throwOnError = throwOnError
if (util.isStream(body)) {
body.on('error', (err) => {
@@ -70,7 +72,7 @@ class RequestHandler extends AsyncResource {
this.context = context
}
- onHeaders (statusCode, rawHeaders, resume) {
+ onHeaders (statusCode, rawHeaders, resume, statusMessage) {
const { callback, opaque, abort, context } = this
if (statusCode < 200) {
@@ -89,6 +91,13 @@ class RequestHandler extends AsyncResource {
const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders)
if (callback !== null) {
+ if (this.throwOnError && statusCode >= 400) {
+ this.runInAsyncScope(callback, null,
+ new ResponseStatusCodeError(`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`, statusCode, headers)
+ )
+ return
+ }
+
this.runInAsyncScope(callback, null, null, {
statusCode,
headers,
diff --git a/deps/undici/src/lib/core/errors.js b/deps/undici/src/lib/core/errors.js
index f480f31a176..a36fd067c9f 100644
--- a/deps/undici/src/lib/core/errors.js
+++ b/deps/undici/src/lib/core/errors.js
@@ -56,6 +56,19 @@ class BodyTimeoutError extends UndiciError {
}
}
+class ResponseStatusCodeError extends UndiciError {
+ constructor (message, statusCode, headers) {
+ super(message)
+ Error.captureStackTrace(this, ResponseStatusCodeError)
+ this.name = 'ResponseStatusCodeError'
+ this.message = message || 'Response Status Code Error'
+ this.code = 'UND_ERR_RESPONSE_STATUS_CODE'
+ this.status = statusCode
+ this.statusCode = statusCode
+ this.headers = headers
+ }
+}
+
class InvalidArgumentError extends UndiciError {
constructor (message) {
super(message)
@@ -186,6 +199,7 @@ module.exports = {
BodyTimeoutError,
RequestContentLengthMismatchError,
ConnectTimeoutError,
+ ResponseStatusCodeError,
InvalidArgumentError,
InvalidReturnValueError,
RequestAbortedError,
diff --git a/deps/undici/src/lib/core/request.js b/deps/undici/src/lib/core/request.js
index f04fe4fab21..2a13b0549a8 100644
--- a/deps/undici/src/lib/core/request.js
+++ b/deps/undici/src/lib/core/request.js
@@ -4,8 +4,8 @@ const {
InvalidArgumentError,
NotSupportedError
} = require('./errors')
-const util = require('./util')
const assert = require('assert')
+const util = require('./util')
const kHandler = Symbol('handler')
@@ -38,11 +38,13 @@ class Request {
method,
body,
headers,
+ query,
idempotent,
blocking,
upgrade,
headersTimeout,
- bodyTimeout
+ bodyTimeout,
+ throwOnError
}, handler) {
if (typeof path !== 'string') {
throw new InvalidArgumentError('path must be a string')
@@ -70,6 +72,8 @@ class Request {
this.bodyTimeout = bodyTimeout
+ this.throwOnError = throwOnError === true
+
this.method = method
if (body == null) {
@@ -97,7 +101,7 @@ class Request {
this.upgrade = upgrade || null
- this.path = path
+ this.path = query ? util.buildURL(path, query) : path
this.origin = origin
diff --git a/deps/undici/src/lib/core/util.js b/deps/undici/src/lib/core/util.js
index 0cb60b0d2a4..635ef2e15f2 100644
--- a/deps/undici/src/lib/core/util.js
+++ b/deps/undici/src/lib/core/util.js
@@ -26,6 +26,51 @@ function isBlobLike (object) {
)
}
+function isObject (val) {
+ return val !== null && typeof val === 'object'
+}
+
+// this escapes all non-uri friendly characters
+function encode (val) {
+ return encodeURIComponent(val)
+}
+
+// based on https://github.com/axios/axios/blob/63e559fa609c40a0a460ae5d5a18c3470ffc6c9e/lib/helpers/buildURL.js (MIT license)
+function buildURL (url, queryParams) {
+ if (url.includes('?') || url.includes('#')) {
+ throw new Error('Query params cannot be passed when url already contains "?" or "#".')
+ }
+ if (!isObject(queryParams)) {
+ throw new Error('Query params must be an object')
+ }
+
+ const parts = []
+ for (let [key, val] of Object.entries(queryParams)) {
+ if (val === null || typeof val === 'undefined') {
+ continue
+ }
+
+ if (!Array.isArray(val)) {
+ val = [val]
+ }
+
+ for (const v of val) {
+ if (isObject(v)) {
+ throw new Error('Passing object as a query param is not supported, please serialize to string up-front')
+ }
+ parts.push(encode(key) + '=' + encode(v))
+ }
+ }
+
+ const serializedParams = parts.join('&')
+
+ if (serializedParams) {
+ url += '?' + serializedParams
+ }
+
+ return url
+}
+
function parseURL (url) {
if (typeof url === 'string') {
url = new URL(url)
@@ -357,5 +402,6 @@ module.exports = {
isBuffer,
validateHandler,
getSocketInfo,
- isFormDataLike
+ isFormDataLike,
+ buildURL
}
diff --git a/deps/undici/src/lib/fetch/file.js b/deps/undici/src/lib/fetch/file.js
index 2b98739d2bb..a9c2355fc89 100644
--- a/deps/undici/src/lib/fetch/file.js
+++ b/deps/undici/src/lib/fetch/file.js
@@ -69,10 +69,6 @@ class File extends Blob {
}
get [Symbol.toStringTag] () {
- if (!(this instanceof File)) {
- throw new TypeError('Illegal invocation')
- }
-
return this.constructor.name
}
}
@@ -190,10 +186,6 @@ class FileLike {
}
get [Symbol.toStringTag] () {
- if (!(this instanceof FileLike)) {
- throw new TypeError('Illegal invocation')
- }
-
return 'File'
}
}
diff --git a/deps/undici/src/lib/fetch/formdata.js b/deps/undici/src/lib/fetch/formdata.js
index 550e1e46947..e12d2b42bd2 100644
--- a/deps/undici/src/lib/fetch/formdata.js
+++ b/deps/undici/src/lib/fetch/formdata.js
@@ -6,6 +6,8 @@ const { File, FileLike } = require('./file')
const { Blob } = require('buffer')
class FormData {
+ static name = 'FormData'
+
constructor (...args) {
if (args.length > 0 && !(args[0]?.constructor?.name === 'HTMLFormElement')) {
throw new TypeError(
@@ -182,10 +184,6 @@ class FormData {
}
get [Symbol.toStringTag] () {
- if (!(this instanceof FormData)) {
- throw new TypeError('Illegal invocation')
- }
-
return this.constructor.name
}
@@ -269,4 +267,4 @@ function makeEntry (name, value, filename) {
return entry
}
-module.exports = { FormData: globalThis.FormData ?? FormData }
+module.exports = { FormData }
diff --git a/deps/undici/src/lib/fetch/index.js b/deps/undici/src/lib/fetch/index.js
index 5dab8a0532f..c1f3391995e 100644
--- a/deps/undici/src/lib/fetch/index.js
+++ b/deps/undici/src/lib/fetch/index.js
@@ -31,7 +31,6 @@ const {
coarsenedSharedCurrentTime,
createDeferredPromise,
isBlobLike,
- CORBCheck,
sameOrigin,
isCancelled,
isAborted
@@ -52,7 +51,6 @@ const EE = require('events')
const { Readable, pipeline } = require('stream')
const { isErrored, isReadable } = require('../core/util')
const { dataURLProcessor } = require('./dataURL')
-const { kIsMockActive } = require('../mock/mock-symbols')
const { TransformStream } = require('stream/web')
/** @type {import('buffer').resolveObjectURL} */
@@ -588,18 +586,8 @@ async function mainFetch (fetchParams, recursive = false) {
// 2. Set request’s response tainting to "opaque".
request.responseTainting = 'opaque'
- // 3. Let noCorsResponse be the result of running scheme fetch given
- // fetchParams.
- const noCorsResponse = await schemeFetch(fetchParams)
-
- // 4. If noCorsResponse is a filtered response or the CORB check with
- // request and noCorsResponse returns allowed, then return noCorsResponse.
- if (noCorsResponse.status === 0 || CORBCheck(request, noCorsResponse) === 'allowed') {
- return noCorsResponse
- }
-
- // 5. Return a new response whose status is noCorsResponse’s status.
- return makeResponse({ status: noCorsResponse.status })
+ // 3. Return the result of running scheme fetch given fetchParams.
+ return await schemeFetch(fetchParams)
}
// request’s current URL’s scheme is not an HTTP(S) scheme
@@ -1923,7 +1911,7 @@ async function httpNetworkFetch (
path: url.pathname + url.search,
origin: url.origin,
method: request.method,
- body: fetchParams.controller.dispatcher[kIsMockActive] ? request.body && request.body.source : body,
+ body: fetchParams.controller.dispatcher.isMockActive ? request.body && request.body.source : body,
headers: [...request.headersList].flat(),
maxRedirections: 0,
bodyTimeout: 300_000,
diff --git a/deps/undici/src/lib/fetch/request.js b/deps/undici/src/lib/fetch/request.js
index c17927ee768..661f5814ba2 100644
--- a/deps/undici/src/lib/fetch/request.js
+++ b/deps/undici/src/lib/fetch/request.js
@@ -516,10 +516,6 @@ class Request {
}
get [Symbol.toStringTag] () {
- if (!(this instanceof Request)) {
- throw new TypeError('Illegal invocation')
- }
-
return this.constructor.name
}
diff --git a/deps/undici/src/lib/fetch/response.js b/deps/undici/src/lib/fetch/response.js
index b8aa4897c1b..03db7eb488e 100644
--- a/deps/undici/src/lib/fetch/response.js
+++ b/deps/undici/src/lib/fetch/response.js
@@ -5,7 +5,7 @@ const { AbortError } = require('../core/errors')
const { extractBody, cloneBody, mixinBody } = require('./body')
const util = require('../core/util')
const { kEnumerableProperty } = util
-const { responseURL, isValidReasonPhrase, toUSVString, isCancelled, isAborted } = require('./util')
+const { responseURL, isValidReasonPhrase, toUSVString, isCancelled, isAborted, serializeJavascriptValueToJSONString } = require('./util')
const {
redirectStatus,
nullBodyStatus,
@@ -35,6 +35,50 @@ class Response {
return responseObject
}
+ // https://fetch.spec.whatwg.org/#dom-response-json
+ static json (data, init = {}) {
+ if (arguments.length === 0) {
+ throw new TypeError(
+ 'Failed to execute \'json\' on \'Response\': 1 argument required, but 0 present.'
+ )
+ }
+
+ if (init === null || typeof init !== 'object') {
+ throw new TypeError(
+ `Failed to execute 'json' on 'Response': init must be a RequestInit, found ${typeof init}.`
+ )
+ }
+
+ init = {
+ status: 200,
+ statusText: '',
+ headers: new HeadersList(),
+ ...init
+ }
+
+ // 1. Let bytes the result of running serialize a JavaScript value to JSON bytes on data.
+ const bytes = new TextEncoder('utf-8').encode(
+ serializeJavascriptValueToJSONString(data)
+ )
+
+ // 2. Let body be the result of extracting bytes.
+ const body = extractBody(bytes)
+
+ // 3. Let responseObject be the result of creating a Response object, given a new response,
+ // "response", and this’s relevant Realm.
+ const relevantRealm = { settingsObject: {} }
+ const responseObject = new Response()
+ responseObject[kRealm] = relevantRealm
+ responseObject[kHeaders][kGuard] = 'response'
+ responseObject[kHeaders][kRealm] = relevantRealm
+
+ // 4. Perform initialize a response given responseObject, init, and (body, "application/json").
+ initializeResponse(responseObject, init, { body: body[0], type: 'application/json' })
+
+ // 5. Return responseObject.
+ return responseObject
+ }
+
// Creates a redirect Response that redirects to url with status status.
static redirect (...args) {
const relevantRealm = { settingsObject: {} }
@@ -105,34 +149,10 @@ class Response {
// TODO
this[kRealm] = { settingsObject: {} }
- // 1. If init["status"] is not in the range 200 to 599, inclusive, then
- // throw a RangeError.
- if ('status' in init && init.status !== undefined) {
- if (!Number.isFinite(init.status)) {
- throw new TypeError()
- }
-
- if (init.status < 200 || init.status > 599) {
- throw new RangeError(
- `Failed to construct 'Response': The status provided (${init.status}) is outside the range [200, 599].`
- )
- }
- }
-
- if ('statusText' in init && init.statusText !== undefined) {
- // 2. If init["statusText"] does not match the reason-phrase token
- // production, then throw a TypeError.
- // See, https://datatracker.ietf.org/doc/html/rfc7230#section-3.1.2:
- // reason-phrase = *( HTAB / SP / VCHAR / obs-text )
- if (!isValidReasonPhrase(String(init.statusText))) {
- throw new TypeError('Invalid statusText')
- }
- }
-
- // 3. Set this’s response to a new response.
+ // 1. Set this’s response to a new response.
this[kState] = makeResponse({})
- // 4. Set this’s headers to a new Headers object with this’s relevant
+ // 2. Set this’s headers to a new Headers object with this’s relevant
// Realm, whose header list is this’s response’s header list and guard
// is "response".
this[kHeaders] = new Headers()
@@ -140,48 +160,20 @@ class Response {
this[kHeaders][kHeadersList] = this[kState].headersList
this[kHeaders][kRealm] = this[kRealm]
- // 5. Set this’s response’s status to init["status"].
- if ('status' in init && init.status !== undefined) {
- this[kState].status = init.status
- }
+ // 3. Let bodyWithType be null.
+ let bodyWithType = null
- // 6. Set this’s response’s status message to init["statusText"].
- if ('statusText' in init && init.statusText !== undefined) {
- this[kState].statusText = String(init.statusText)
- }
-
- // 7. If init["headers"] exists, then fill this’s headers with init["headers"].
- if ('headers' in init) {
- fill(this[kState].headersList, init.headers)
- }
-
- // 8. If body is non-null, then:
+ // 4. If body is non-null, then set bodyWithType to the result of extracting body.
if (body != null) {
- // 1. If init["status"] is a null body status, then throw a TypeError.
- if (nullBodyStatus.includes(init.status)) {
- throw new TypeError('Response with null body status cannot have body')
- }
-
- // 2. Let Content-Type be null.
- // 3. Set this’s response’s body and Content-Type to the result of
- // extracting body.
- const [extractedBody, contentType] = extractBody(body)
- this[kState].body = extractedBody
-
- // 4. If Content-Type is non-null and this’s response’s header list does
- // not contain `Content-Type`, then append `Content-Type`/Content-Type
- // to this’s response’s header list.
- if (contentType && !this.headers.has('content-type')) {
- this.headers.append('content-type', contentType)
- }
+ const [extractedBody, type] = extractBody(body)
+ bodyWithType = { body: extractedBody, type }
}
+
+ // 5. Perform initialize a response given this, init, and bodyWithType.
+ initializeResponse(this, init, bodyWithType)
}
get [Symbol.toStringTag] () {
- if (!(this instanceof Response)) {
- throw new TypeError('Illegal invocation')
- }
-
return this.constructor.name
}
@@ -477,6 +469,57 @@ function makeAppropriateNetworkError (fetchParams) {
: makeNetworkError(fetchParams.controller.terminated.reason)
}
+// https://whatpr.org/fetch/1392.html#initialize-a-response
+function initializeResponse (response, init, body) {
+ // 1. If init["status"] is not in the range 200 to 599, inclusive, then
+ // throw a RangeError.
+ if (init.status != null && (init.status < 200 || init.status > 599)) {
+ throw new RangeError('init["status"] must be in the range of 200 to 599, inclusive.')
+ }
+
+ // 2. If init["statusText"] does not match the reason-phrase token production,
+ // then throw a TypeError.
+ if ('statusText' in init && init.statusText != null) {
+ // See, https://datatracker.ietf.org/doc/html/rfc7230#section-3.1.2:
+ // reason-phrase = *( HTAB / SP / VCHAR / obs-text )
+ if (!isValidReasonPhrase(String(init.statusText))) {
+ throw new TypeError('Invalid statusText')
+ }
+ }
+
+ // 3. Set response’s response’s status to init["status"].
+ if ('status' in init && init.status != null) {
+ response[kState].status = init.status
+ }
+
+ // 4. Set response’s response’s status message to init["statusText"].
+ if ('statusText' in init && init.statusText != null) {
+ response[kState].statusText = init.statusText
+ }
+
+ // 5. If init["headers"] exists, then fill response’s headers with init["headers"].
+ if ('headers' in init && init.headers != null) {
+ fill(response[kState].headersList, init.headers)
+ }
+
+ // 6. If body was given, then:
+ if (body) {
+ // 1. If response's status is a null body status, then throw a TypeError.
+ if (nullBodyStatus.includes(response.status)) {
+ throw new TypeError()
+ }
+
+ // 2. Set response's body to body's body.
+ response[kState].body = body.body
+
+ // 3. If body's type is non-null and response's header list does not contain
+ // `Content-Type`, then append (`Content-Type`, body's type) to response's header list.
+ if (body.type != null && !response[kState].headersList.has('Content-Type')) {
+ response[kState].headersList.append('content-type', body.type)
+ }
+ }
+}
+
module.exports = {
makeNetworkError,
makeResponse,
diff --git a/deps/undici/src/lib/fetch/util.js b/deps/undici/src/lib/fetch/util.js
index 0116f67a8b6..1c67f9c7c84 100644
--- a/deps/undici/src/lib/fetch/util.js
+++ b/deps/undici/src/lib/fetch/util.js
@@ -3,6 +3,7 @@
const { redirectStatus } = require('./constants')
const { performance } = require('perf_hooks')
const { isBlobLike, toUSVString, ReadableStreamFrom } = require('../core/util')
+const assert = require('assert')
let File
@@ -316,47 +317,6 @@ function sameOrigin (A, B) {
return false
}
-// https://fetch.spec.whatwg.org/#corb-check
-function CORBCheck (request, response) {
- // 1. If request’s initiator is "download", then return allowed.
- if (request.initiator === 'download') {
- return 'allowed'
- }
-
- // 2. If request’s current URL’s scheme is not an HTTP(S) scheme, then return allowed.
- if (!/^https?$/.test(request.currentURL.scheme)) {
- return 'allowed'
- }
-
- // 3. Let mimeType be the result of extracting a MIME type from response’s header list.
- const mimeType = response.headersList.get('content-type')
-
- // 4. If mimeType is failure, then return allowed.
- if (mimeType === '') {
- return 'allowed'
- }
-
- // 5. If response’s status is 206 and mimeType is a CORB-protected MIME type, then return blocked.
-
- const isCORBProtectedMIME =
- (/^text\/html\b/.test(mimeType) ||
- /^application\/javascript\b/.test(mimeType) ||
- /^application\/xml\b/.test(mimeType)) && !/^application\/xml\+svg\b/.test(mimeType)
-
- if (response.status === 206 && isCORBProtectedMIME) {
- return 'blocked'
- }
-
- // 6. If determine nosniff with response’s header list is true and mimeType is a CORB-protected MIME type or its essence is "text/plain", then return blocked.
- // https://fetch.spec.whatwg.org/#determinenosniff
- if (response.headersList.get('x-content-type-options') && isCORBProtectedMIME) {
- return 'blocked'
- }
-
- // 7. Return allowed.
- return 'allowed'
-}
-
function createDeferredPromise () {
let res
let rej
@@ -384,6 +344,23 @@ function normalizeMethod (method) {
: method
}
+// https://infra.spec.whatwg.org/#serialize-a-javascript-value-to-a-json-string
+function serializeJavascriptValueToJSONString (value) {
+ // 1. Let result be ? Call(%JSON.stringify%, undefined, « value »).
+ const result = JSON.stringify(value)
+
+ // 2. If result is undefined, then throw a TypeError.
+ if (result === undefined) {
+ throw new TypeError('Value is not JSON serializable')
+ }
+
+ // 3. Assert: result is a string.
+ assert(typeof result === 'string')
+
+ // 4. Return result.
+ return result
+}
+
module.exports = {
isAborted,
isCancelled,
@@ -412,6 +389,6 @@ module.exports = {
isFileLike,
isValidReasonPhrase,
sameOrigin,
- CORBCheck,
- normalizeMethod
+ normalizeMethod,
+ serializeJavascriptValueToJSONString
}
diff --git a/deps/undici/src/lib/mock/mock-agent.js b/deps/undici/src/lib/mock/mock-agent.js
index 093da5e50a9..828e8af174d 100644
--- a/deps/undici/src/lib/mock/mock-agent.js
+++ b/deps/undici/src/lib/mock/mock-agent.js
@@ -96,6 +96,12 @@ class MockAgent extends Dispatcher {
this[kNetConnect] = false
}
+ // This is required to bypass issues caused by using global symbols - see:
+ // https://github.com/nodejs/undici/issues/1447
+ get isMockActive () {
+ return this[kIsMockActive]
+ }
+
[kMockAgentSet] (origin, dispatcher) {
this[kClients].set(origin, new FakeWeakRef(dispatcher))
}
diff --git a/deps/undici/src/lib/mock/mock-utils.js b/deps/undici/src/lib/mock/mock-utils.js
index a81f05af045..a9ab94f36ae 100644
--- a/deps/undici/src/lib/mock/mock-utils.js
+++ b/deps/undici/src/lib/mock/mock-utils.js
@@ -6,7 +6,6 @@ const {
kMockAgent,
kOriginalDispatch,
kOrigin,
- kIsMockActive,
kGetNetConnect
} = require('./mock-symbols')
@@ -302,7 +301,7 @@ function buildMockDispatch () {
const originalDispatch = this[kOriginalDispatch]
return function dispatch (opts, handler) {
- if (agent[kIsMockActive]) {
+ if (agent.isMockActive) {
try {
mockDispatch.call(this, opts, handler)
} catch (error) {
diff --git a/deps/undici/src/lib/proxy-agent.js b/deps/undici/src/lib/proxy-agent.js
index 2da6c7a5036..37a41680617 100644
--- a/deps/undici/src/lib/proxy-agent.js
+++ b/deps/undici/src/lib/proxy-agent.js
@@ -1,7 +1,6 @@
'use strict'
const { kProxy, kClose, kDestroy } = require('./core/symbols')
-const { URL } = require('url')
const Agent = require('./agent')
const DispatcherBase = require('./dispatcher-base')
const { InvalidArgumentError } = require('./core/errors')
diff --git a/deps/undici/src/package.json b/deps/undici/src/package.json
index 763eed02078..b30753c16d9 100644
--- a/deps/undici/src/package.json
+++ b/deps/undici/src/package.json
@@ -1,6 +1,6 @@
{
"name": "undici",
- "version": "5.2.0",
+ "version": "5.3.0",
"description": "An HTTP/1.1 client, written from scratch for Node.js",
"homepage": "https://undici.nodejs.org",
"bugs": {
@@ -48,7 +48,7 @@
"lint:fix": "standard --fix | snazzy",
"test": "npm run test:tap && npm run test:node-fetch && npm run test:fetch && npm run test:jest && tsd",
"test:node-fetch": "node scripts/verifyVersion.js 16 || mocha test/node-fetch",
- "test:fetch": "node scripts/verifyVersion.js 16 || tap test/fetch/*.js",
+ "test:fetch": "node scripts/verifyVersion.js 16 || (npm run build:node && tap test/fetch/*.js)",
"test:jest": "jest",
"test:tap": "tap test/*.js test/diagnostics-channel/*.js",
"test:tdd": "tap test/*.js test/diagnostics-channel/*.js -w",
@@ -91,6 +91,7 @@
"sinon": "^14.0.0",
"snazzy": "^9.0.0",
"standard": "^17.0.0",
+ "table": "^6.8.0",
"tap": "^16.1.0",
"tsd": "^0.20.0",
"wait-on": "^6.0.0"
diff --git a/deps/undici/src/types/diagnostics-channel.d.ts b/deps/undici/src/types/diagnostics-channel.d.ts
new file mode 100644
index 00000000000..8bb1926506e
--- /dev/null
+++ b/deps/undici/src/types/diagnostics-channel.d.ts
@@ -0,0 +1,66 @@
+import { Socket } from "net";
+import { connector } from "./connector";
+import { HttpMethod } from "./dispatcher";
+
+declare namespace DiagnosticsChannel {
+ interface Request {
+ origin?: string | URL;
+ completed: boolean;
+ method?: HttpMethod;
+ path: string;
+ headers: string;
+ addHeader(key: string, value: string): Request;
+ }
+ interface Response {
+ statusCode: number;
+ statusText: string;
+ headers: Array<Buffer>;
+ }
+ type Error = unknown;
+ interface ConnectParams {
+ host: URL["host"];
+ hostname: URL["hostname"];
+ protocol: URL["protocol"];
+ port: URL["port"];
+ servername: string | null;
+ }
+ type Connector = typeof connector;
+ export interface RequestCreateMessage {
+ request: Request;
+ }
+ export interface RequestBodySentMessage {
+ request: Request;
+ }
+ export interface RequestHeadersMessage {
+ request: Request;
+ response: Response;
+ }
+ export interface RequestTrailersMessage {
+ request: Request;
+ trailers: Array<Buffer>;
+ }
+ export interface RequestErrorMessage {
+ request: Request;
+ error: Error;
+ }
+ export interface ClientSendHeadersMessage {
+ request: Request;
+ headers: string;
+ socket: Socket;
+ }
+ export interface ClientBeforeConnectMessage {
+ connectParams: ConnectParams;
+ connector: Connector;
+ }
+ export interface ClientConnectedMessage {
+ socket: Socket;
+ connectParams: ConnectParams;
+ connector: Connector;
+ }
+ export interface ClientConnectErrorMessage {
+ error: Error;
+ socket: Socket;
+ connectParams: ConnectParams;
+ connector: Connector;
+ }
+}
diff --git a/deps/undici/src/types/dispatcher.d.ts b/deps/undici/src/types/dispatcher.d.ts
index 9b2af26e6d2..4bc3241ac3d 100644
--- a/deps/undici/src/types/dispatcher.d.ts
+++ b/deps/undici/src/types/dispatcher.d.ts
@@ -47,6 +47,8 @@ declare namespace Dispatcher {
body?: string | Buffer | Uint8Array | Readable | null | FormData;
/** Default: `null` */
headers?: IncomingHttpHeaders | string[] | null;
+ /** Query string params to be embedded in the request URL. Default: `null` */
+ query?: Record<string, any>;
/** Whether the requests can be safely retried or not. If `false` the request won't be sent until all preceding requests in the pipeline have completed. Default: `true` if `method` is `HEAD` or `GET`. */
idempotent?: boolean;
/** Upgrade the request. Should be used to specify the kind of upgrade i.e. `'Websocket'`. Default: `method === 'CONNECT' || null`. */
@@ -55,6 +57,8 @@ declare namespace Dispatcher {
headersTimeout?: number | null;
/** The timeout after which a request will time out, in milliseconds. Monitors time between receiving body data. Use 0 to disable it entirely. Defaults to 30 seconds. */
bodyTimeout?: number | null;
+ /** Whether Undici should throw an error upon receiving a 4xx or 5xx response from the server. Defaults to false */
+ throwOnError?: boolean;
}
export interface ConnectOptions {
path: string;
diff --git a/deps/undici/src/types/fetch.d.ts b/deps/undici/src/types/fetch.d.ts
index 1b8692b251c..47a08dd0510 100644
--- a/deps/undici/src/types/fetch.d.ts
+++ b/deps/undici/src/types/fetch.d.ts
@@ -101,19 +101,19 @@ type RequestDestination =
| 'xslt'
export interface RequestInit {
- readonly method?: string
- readonly keepalive?: boolean
- readonly headers?: HeadersInit
- readonly body?: BodyInit
- readonly redirect?: RequestRedirect
- readonly integrity?: string
- readonly signal?: AbortSignal
- readonly credentials?: RequestCredentials
- readonly mode?: RequestMode
- readonly referrer?: string
- readonly referrerPolicy?: ReferrerPolicy
- readonly window?: null
- readonly dispatcher?: Dispatcher
+ method?: string
+ keepalive?: boolean
+ headers?: HeadersInit
+ body?: BodyInit
+ redirect?: RequestRedirect
+ integrity?: string
+ signal?: AbortSignal
+ credentials?: RequestCredentials
+ mode?: RequestMode
+ referrer?: string
+ referrerPolicy?: ReferrerPolicy
+ window?: null
+ dispatcher?: Dispatcher
}
export type ReferrerPolicy =
@@ -199,5 +199,6 @@ export declare class Response implements BodyMixin {
readonly clone: () => Response
static error (): Response
+ static json(data: any, init?: ResponseInit): Response
static redirect (url: string | URL, status: ResponseRedirectStatus): Response
}
diff --git a/deps/undici/undici.js b/deps/undici/undici.js
index 86749222920..16c98d7469e 100644
--- a/deps/undici/undici.js
+++ b/deps/undici/undici.js
@@ -1,8 +1,14 @@
"use strict";
+var __defProp = Object.defineProperty;
var __getOwnPropNames = Object.getOwnPropertyNames;
+var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __commonJS = (cb, mod) => function __require() {
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
+var __publicField = (obj, key, value) => {
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
+ return value;
+};
// lib/core/errors.js
var require_errors = __commonJS({
@@ -58,6 +64,18 @@ var require_errors = __commonJS({
this.code = "UND_ERR_BODY_TIMEOUT";
}
};
+ var ResponseStatusCodeError = class extends UndiciError {
+ constructor(message, statusCode, headers) {
+ super(message);
+ Error.captureStackTrace(this, ResponseStatusCodeError);
+ this.name = "ResponseStatusCodeError";
+ this.message = message || "Response Status Code Error";
+ this.code = "UND_ERR_RESPONSE_STATUS_CODE";
+ this.status = statusCode;
+ this.statusCode = statusCode;
+ this.headers = headers;
+ }
+ };
var InvalidArgumentError = class extends UndiciError {
constructor(message) {
super(message);
@@ -176,6 +194,7 @@ var require_errors = __commonJS({
BodyTimeoutError,
RequestContentLengthMismatchError,
ConnectTimeoutError,
+ ResponseStatusCodeError,
InvalidArgumentError,
InvalidReturnValueError,
RequestAbortedError,
@@ -664,6 +683,40 @@ var require_util = __commonJS({
function isBlobLike(object) {
return Blob && object instanceof Blob || object && typeof object === "object" && (typeof object.stream === "function" || typeof object.arrayBuffer === "function") && /^(Blob|File)$/.test(object[Symbol.toStringTag]);
}
+ function isObject(val) {
+ return val !== null && typeof val === "object";
+ }
+ function encode(val) {
+ return encodeURIComponent(val);
+ }
+ function buildURL(url, queryParams) {
+ if (url.includes("?") || url.includes("#")) {
+ throw new Error('Query params cannot be passed when url already contains "?" or "#".');
+ }
+ if (!isObject(queryParams)) {
+ throw new Error("Query params must be an object");
+ }
+ const parts = [];
+ for (let [key, val] of Object.entries(queryParams)) {
+ if (val === null || typeof val === "undefined") {
+ continue;
+ }
+ if (!Array.isArray(val)) {
+ val = [val];
+ }
+ for (const v of val) {
+ if (isObject(v)) {
+ throw new Error("Passing object as a query param is not supported, please serialize to string up-front");
+ }
+ parts.push(encode(key) + "=" + encode(v));
+ }
+ }
+ const serializedParams = parts.join("&");
+ if (serializedParams) {
+ url += "?" + serializedParams;
+ }
+ return url;
+ }
function parseURL(url) {
if (typeof url === "string") {
url = new URL(url);
@@ -911,7 +964,8 @@ var require_util = __commonJS({
isBuffer,
validateHandler,
getSocketInfo,
- isFormDataLike
+ isFormDataLike,
+ buildURL
};
}
});
@@ -1056,9 +1110,6 @@ var require_file = __commonJS({
return this[kState].lastModified;
}
get [Symbol.toStringTag]() {
- if (!(this instanceof File)) {
- throw new TypeError("Illegal invocation");
- }
return this.constructor.name;
}
};
@@ -1123,9 +1174,6 @@ var require_file = __commonJS({
return this[kState].lastModified;
}
get [Symbol.toStringTag]() {
- if (!(this instanceof FileLike)) {
- throw new TypeError("Illegal invocation");
- }
return "File";
}
};
@@ -1140,6 +1188,7 @@ var require_util2 = __commonJS({
var { redirectStatus } = require_constants();
var { performance } = require("perf_hooks");
var { isBlobLike, toUSVString, ReadableStreamFrom } = require_util();
+ var assert = require("assert");
var File;
var badPorts = [
"1",
@@ -1367,26 +1416,6 @@ var require_util2 = __commonJS({
}
return false;
}
- function CORBCheck(request, response) {
- if (request.initiator === "download") {
- return "allowed";
- }
- if (!/^https?$/.test(request.currentURL.scheme)) {
- return "allowed";
- }
- const mimeType = response.headersList.get("content-type");
- if (mimeType === "") {
- return "allowed";
- }
- const isCORBProtectedMIME = (/^text\/html\b/.test(mimeType) || /^application\/javascript\b/.test(mimeType) || /^application\/xml\b/.test(mimeType)) && !/^application\/xml\+svg\b/.test(mimeType);
- if (response.status === 206 && isCORBProtectedMIME) {
- return "blocked";
- }
- if (response.headersList.get("x-content-type-options") && isCORBProtectedMIME) {
- return "blocked";
- }
- return "allowed";
- }
function createDeferredPromise() {
let res;
let rej;
@@ -1405,6 +1434,14 @@ var require_util2 = __commonJS({
function normalizeMethod(method) {
return /^(DELETE|GET|HEAD|OPTIONS|POST|PUT)$/i.test(method) ? method.toUpperCase() : method;
}
+ function serializeJavascriptValueToJSONString(value) {
+ const result = JSON.stringify(value);
+ if (result === void 0) {
+ throw new TypeError("Value is not JSON serializable");
+ }
+ assert(typeof result === "string");
+ return result;
+ }
module2.exports = {
isAborted,
isCancelled,
@@ -1433,8 +1470,8 @@ var require_util2 = __commonJS({
isFileLike,
isValidReasonPhrase,
sameOrigin,
- CORBCheck,
- normalizeMethod
+ normalizeMethod,
+ serializeJavascriptValueToJSONString
};
}
});
@@ -1447,7 +1484,7 @@ var require_formdata = __commonJS({
var { kState } = require_symbols2();
var { File, FileLike } = require_file();
var { Blob } = require("buffer");
- var FormData = class {
+ var _FormData = class {
constructor(...args) {
if (args.length > 0 && !(args[0]?.constructor?.name === "HTMLFormElement")) {
throw new TypeError("Failed to construct 'FormData': parameter 1 is not of type 'HTMLFormElement'");
@@ -1455,7 +1492,7 @@ var require_formdata = __commonJS({
this[kState] = [];
}
append(...args) {
- if (!(this instanceof FormData)) {
+ if (!(this instanceof _FormData)) {
throw new TypeError("Illegal invocation");
}
if (args.length < 2) {
@@ -1471,7 +1508,7 @@ var require_formdata = __commonJS({
this[kState].push(entry);
}
delete(...args) {
- if (!(this instanceof FormData)) {
+ if (!(this instanceof _FormData)) {
throw new TypeError("Illegal invocation");
}
if (args.length < 1) {
@@ -1487,7 +1524,7 @@ var require_formdata = __commonJS({
this[kState] = next;
}
get(...args) {
- if (!(this instanceof FormData)) {
+ if (!(this instanceof _FormData)) {
throw new TypeError("Illegal invocation");
}
if (args.length < 1) {
@@ -1501,7 +1538,7 @@ var require_formdata = __commonJS({
return this[kState][idx].value;
}
getAll(...args) {
- if (!(this instanceof FormData)) {
+ if (!(this instanceof _FormData)) {
throw new TypeError("Illegal invocation");
}
if (args.length < 1) {
@@ -1511,7 +1548,7 @@ var require_formdata = __commonJS({
return this[kState].filter((entry) => entry.name === name).map((entry) => entry.value);
}
has(...args) {
- if (!(this instanceof FormData)) {
+ if (!(this instanceof _FormData)) {
throw new TypeError("Illegal invocation");
}
if (args.length < 1) {
@@ -1521,7 +1558,7 @@ var require_formdata = __commonJS({
return this[kState].findIndex((entry) => entry.name === name) !== -1;
}
set(...args) {
- if (!(this instanceof FormData)) {
+ if (!(this instanceof _FormData)) {
throw new TypeError("Illegal invocation");
}
if (args.length < 2) {
@@ -1546,13 +1583,10 @@ var require_formdata = __commonJS({
}
}
get [Symbol.toStringTag]() {
- if (!(this instanceof FormData)) {
- throw new TypeError("Illegal invocation");
- }
return this.constructor.name;
}
*entries() {
- if (!(this instanceof FormData)) {
+ if (!(this instanceof _FormData)) {
throw new TypeError("Illegal invocation");
}
for (const pair of this) {
@@ -1560,7 +1594,7 @@ var require_formdata = __commonJS({
}
}
*keys() {
- if (!(this instanceof FormData)) {
+ if (!(this instanceof _FormData)) {
throw new TypeError("Illegal invocation");
}
for (const [key] of this) {
@@ -1568,7 +1602,7 @@ var require_formdata = __commonJS({
}
}
*values() {
- if (!(this instanceof FormData)) {
+ if (!(this instanceof _FormData)) {
throw new TypeError("Illegal invocation");
}
for (const [, value] of this) {
@@ -1581,6 +1615,8 @@ var require_formdata = __commonJS({
}
}
};
+ var FormData = _FormData;
+ __publicField(FormData, "name", "FormData");
function makeEntry(name, value, filename) {
const entry = {
name: null,
@@ -1596,7 +1632,7 @@ var require_formdata = __commonJS({
entry.value = value;
return entry;
}
- module2.exports = { FormData: globalThis.FormData ?? FormData };
+ module2.exports = { FormData };
}
});
@@ -1833,8 +1869,8 @@ var require_request = __commonJS({
InvalidArgumentError,
NotSupportedError
} = require_errors();
- var util = require_util();
var assert = require("assert");
+ var util = require_util();
var kHandler = Symbol("handler");
var channels = {};
var extractBody;
@@ -1861,11 +1897,13 @@ var require_request = __commonJS({
method,
body,
headers,
+ query,
idempotent,
blocking,
upgrade,
headersTimeout,
- bodyTimeout
+ bodyTimeout,
+ throwOnError
}, handler) {
if (typeof path !== "string") {
throw new InvalidArgumentError("path must be a string");
@@ -1886,6 +1924,7 @@ var require_request = __commonJS({
}
this.headersTimeout = headersTimeout;
this.bodyTimeout = bodyTimeout;
+ this.throwOnError = throwOnError === true;
this.method = method;
if (body == null) {
this.body = null;
@@ -1907,7 +1946,7 @@ var require_request = __commonJS({
this.completed = false;
this.aborted = false;
this.upgrade = upgrade || null;
- this.path = path;
+ this.path = query ? util.buildURL(path, query) : path;
this.origin = origin;
this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent;
this.blocking = blocking == null ? false : blocking;
@@ -4462,7 +4501,7 @@ var require_response = __commonJS({
var { extractBody, cloneBody, mixinBody } = require_body();
var util = require_util();
var { kEnumerableProperty } = util;
- var { responseURL, isValidReasonPhrase, toUSVString, isCancelled, isAborted } = require_util2();
+ var { responseURL, isValidReasonPhrase, toUSVString, isCancelled, isAborted, serializeJavascriptValueToJSONString } = require_util2();
var {
redirectStatus,
nullBodyStatus,
@@ -4483,6 +4522,29 @@ var require_response = __commonJS({
responseObject[kHeaders][kRealm] = relevantRealm;
return responseObject;
}
+ static json(data, init = {}) {
+ if (arguments.length === 0) {
+ throw new TypeError("Failed to execute 'json' on 'Response': 1 argument required, but 0 present.");
+ }
+ if (init === null || typeof init !== "object") {
+ throw new TypeError(`Failed to execute 'json' on 'Response': init must be a RequestInit, found ${typeof init}.`);
+ }
+ init = {
+ status: 200,
+ statusText: "",
+ headers: new HeadersList(),
+ ...init
+ };
+ const bytes = new TextEncoder("utf-8").encode(serializeJavascriptValueToJSONString(data));
+ const body = extractBody(bytes);
+ const relevantRealm = { settingsObject: {} };
+ const responseObject = new Response();
+ responseObject[kRealm] = relevantRealm;
+ responseObject[kHeaders][kGuard] = "response";
+ responseObject[kHeaders][kRealm] = relevantRealm;
+ initializeResponse(responseObject, init, { body: body[0], type: "application/json" });
+ return responseObject;
+ }
static redirect(...args) {
const relevantRealm = { settingsObject: {} };
if (args.length < 1) {
@@ -4517,48 +4579,19 @@ var require_response = __commonJS({
const body = args.length >= 1 ? args[0] : null;
const init = args.length >= 2 ? args[1] ?? {} : {};
this[kRealm] = { settingsObject: {} };
- if ("status" in init && init.status !== void 0) {
- if (!Number.isFinite(init.status)) {
- throw new TypeError();
- }
- if (init.status < 200 || init.status > 599) {
- throw new RangeError(`Failed to construct 'Response': The status provided (${init.status}) is outside the range [200, 599].`);
- }
- }
- if ("statusText" in init && init.statusText !== void 0) {
- if (!isValidReasonPhrase(String(init.statusText))) {
- throw new TypeError("Invalid statusText");
- }
- }
this[kState] = makeResponse({});
this[kHeaders] = new Headers();
this[kHeaders][kGuard] = "response";
this[kHeaders][kHeadersList] = this[kState].headersList;
this[kHeaders][kRealm] = this[kRealm];
- if ("status" in init && init.status !== void 0) {
- this[kState].status = init.status;
- }
- if ("statusText" in init && init.statusText !== void 0) {
- this[kState].statusText = String(init.statusText);
- }
- if ("headers" in init) {
- fill(this[kState].headersList, init.headers);
- }
+ let bodyWithType = null;
if (body != null) {
- if (nullBodyStatus.includes(init.status)) {
- throw new TypeError("Response with null body status cannot have body");
- }
- const [extractedBody, contentType] = extractBody(body);
- this[kState].body = extractedBody;
- if (contentType && !this.headers.has("content-type")) {
- this.headers.append("content-type", contentType);
- }
+ const [extractedBody, type] = extractBody(body);
+ bodyWithType = { body: extractedBody, type };
}
+ initializeResponse(this, init, bodyWithType);
}
get [Symbol.toStringTag]() {
- if (!(this instanceof Response)) {
- throw new TypeError("Illegal invocation");
- }
return this.constructor.name;
}
get type() {
@@ -4746,6 +4779,34 @@ var require_response = __commonJS({
assert(isCancelled(fetchParams));
return isAborted(fetchParams) ? makeNetworkError(new AbortError()) : makeNetworkError(fetchParams.controller.terminated.reason);
}
+ function initializeResponse(response, init, body) {
+ if (init.status != null && (init.status < 200 || init.status > 599)) {
+ throw new RangeError('init["status"] must be in the range of 200 to 599, inclusive.');
+ }
+ if ("statusText" in init && init.statusText != null) {
+ if (!isValidReasonPhrase(String(init.statusText))) {
+ throw new TypeError("Invalid statusText");
+ }
+ }
+ if ("status" in init && init.status != null) {
+ response[kState].status = init.status;
+ }
+ if ("statusText" in init && init.statusText != null) {
+ response[kState].statusText = init.statusText;
+ }
+ if ("headers" in init && init.headers != null) {
+ fill(response[kState].headersList, init.headers);
+ }
+ if (body) {
+ if (nullBodyStatus.includes(response.status)) {
+ throw new TypeError();
+ }
+ response[kState].body = body.body;
+ if (body.type != null && !response[kState].headersList.has("Content-Type")) {
+ response[kState].headersList.append("content-type", body.type);
+ }
+ }
+ }
module2.exports = {
makeNetworkError,
makeResponse,
@@ -5020,9 +5081,6 @@ var require_request2 = __commonJS({
this[kState].body = finalBody;
}
get [Symbol.toStringTag]() {
- if (!(this instanceof Request)) {
- throw new TypeError("Illegal invocation");
- }
return this.constructor.name;
}
get method() {
@@ -5414,34 +5472,6 @@ var require_dataURL = __commonJS({
}
});
-// lib/mock/mock-symbols.js
-var require_mock_symbols = __commonJS({
- "lib/mock/mock-symbols.js"(exports2, module2) {
- "use strict";
- module2.exports = {
- kAgent: Symbol("agent"),
- kOptions: Symbol("options"),
- kFactory: Symbol("factory"),
- kDispatches: Symbol("dispatches"),
- kDispatchKey: Symbol("dispatch key"),
- kDefaultHeaders: Symbol("default headers"),
- kDefaultTrailers: Symbol("default trailers"),
- kContentLength: Symbol("content length"),
- kMockAgent: Symbol("mock agent"),
- kMockAgentSet: Symbol("mock agent set"),
- kMockAgentGet: Symbol("mock agent get"),
- kMockDispatch: Symbol("mock dispatch"),
- kClose: Symbol("close"),
- kOriginalClose: Symbol("original agent close"),
- kOrigin: Symbol("origin"),
- kIsMockActive: Symbol("is mock active"),
- kNetConnect: Symbol("net connect"),
- kGetNetConnect: Symbol("get net connect"),
- kConnected: Symbol("connected")
- };
- }
-});
-
// lib/fetch/index.js
var require_fetch = __commonJS({
"lib/fetch/index.js"(exports2, module2) {
@@ -5475,7 +5505,6 @@ var require_fetch = __commonJS({
coarsenedSharedCurrentTime,
createDeferredPromise,
isBlobLike,
- CORBCheck,
sameOrigin,
isCancelled,
isAborted
@@ -5496,7 +5525,6 @@ var require_fetch = __commonJS({
var { Readable, pipeline } = require("stream");
var { isErrored, isReadable } = require_util();
var { dataURLProcessor } = require_dataURL();
- var { kIsMockActive } = require_mock_symbols();
var { TransformStream } = require("stream/web");
var resolveObjectURL;
var ReadableStream;
@@ -5731,11 +5759,7 @@ var require_fetch = __commonJS({
return makeNetworkError('redirect mode cannot be "follow" for "no-cors" request');
}
request.responseTainting = "opaque";
- const noCorsResponse = await schemeFetch(fetchParams);
- if (noCorsResponse.status === 0 || CORBCheck(request, noCorsResponse) === "allowed") {
- return noCorsResponse;
- }
- return makeResponse({ status: noCorsResponse.status });
+ return await schemeFetch(fetchParams);
}
if (!/^https?:/.test(requestCurrentURL(request).protocol)) {
return makeNetworkError("URL scheme must be a HTTP(S) scheme");
@@ -6275,7 +6299,7 @@ var require_fetch = __commonJS({
path: url.pathname + url.search,
origin: url.origin,
method: request.method,
- body: fetchParams.controller.dispatcher[kIsMockActive] ? request.body && request.body.source : body,
+ body: fetchParams.controller.dispatcher.isMockActive ? request.body && request.body.source : body,
headers: [...request.headersList].flat(),
maxRedirections: 0,
bodyTimeout: 3e5,