aboutsummaryrefslogtreecommitdiffstats
path: root/vanilla/node_modules/undici/lib/handler
diff options
context:
space:
mode:
authorAdam Mathes <adam@adammathes.com>2026-02-14 14:46:37 -0800
committerAdam Mathes <adam@adammathes.com>2026-02-14 14:46:37 -0800
commitafa87af01c79a9baa539f2992d32154d2a4739bd (patch)
tree92c7416db734270a2fee1d72ee9cc119379ff8e1 /vanilla/node_modules/undici/lib/handler
parent3b927e84d200402281f68181cd4253bc77e5528d (diff)
downloadneko-afa87af01c79a9baa539f2992d32154d2a4739bd.tar.gz
neko-afa87af01c79a9baa539f2992d32154d2a4739bd.tar.bz2
neko-afa87af01c79a9baa539f2992d32154d2a4739bd.zip
task: delete vanilla js prototype\n\n- Removed vanilla/ directory and web/dist/vanilla directory\n- Updated Makefile, Dockerfile, and CI workflow to remove vanilla references\n- Cleaned up web/web.go to remove vanilla embed and routes\n- Verified build and tests pass\n\nCloses NK-2tcnmq
Diffstat (limited to 'vanilla/node_modules/undici/lib/handler')
-rw-r--r--vanilla/node_modules/undici/lib/handler/cache-handler.js561
-rw-r--r--vanilla/node_modules/undici/lib/handler/cache-revalidation-handler.js124
-rw-r--r--vanilla/node_modules/undici/lib/handler/decorator-handler.js67
-rw-r--r--vanilla/node_modules/undici/lib/handler/deduplication-handler.js216
-rw-r--r--vanilla/node_modules/undici/lib/handler/redirect-handler.js237
-rw-r--r--vanilla/node_modules/undici/lib/handler/retry-handler.js394
-rw-r--r--vanilla/node_modules/undici/lib/handler/unwrap-handler.js96
-rw-r--r--vanilla/node_modules/undici/lib/handler/wrap-handler.js95
8 files changed, 0 insertions, 1790 deletions
diff --git a/vanilla/node_modules/undici/lib/handler/cache-handler.js b/vanilla/node_modules/undici/lib/handler/cache-handler.js
deleted file mode 100644
index 93a70e8..0000000
--- a/vanilla/node_modules/undici/lib/handler/cache-handler.js
+++ /dev/null
@@ -1,561 +0,0 @@
-'use strict'
-
-const util = require('../core/util')
-const {
- parseCacheControlHeader,
- parseVaryHeader,
- isEtagUsable
-} = require('../util/cache')
-const { parseHttpDate } = require('../util/date.js')
-
-function noop () {}
-
-// Status codes that we can use some heuristics on to cache
-const HEURISTICALLY_CACHEABLE_STATUS_CODES = [
- 200, 203, 204, 206, 300, 301, 308, 404, 405, 410, 414, 501
-]
-
-// Status codes which semantic is not handled by the cache
-// https://datatracker.ietf.org/doc/html/rfc9111#section-3
-// This list should not grow beyond 206 unless the RFC is updated
-// by a newer one including more. Please introduce another list if
-// implementing caching of responses with the 'must-understand' directive.
-const NOT_UNDERSTOOD_STATUS_CODES = [
- 206
-]
-
-const MAX_RESPONSE_AGE = 2147483647000
-
-/**
- * @typedef {import('../../types/dispatcher.d.ts').default.DispatchHandler} DispatchHandler
- *
- * @implements {DispatchHandler}
- */
-class CacheHandler {
- /**
- * @type {import('../../types/cache-interceptor.d.ts').default.CacheKey}
- */
- #cacheKey
-
- /**
- * @type {import('../../types/cache-interceptor.d.ts').default.CacheHandlerOptions['type']}
- */
- #cacheType
-
- /**
- * @type {number | undefined}
- */
- #cacheByDefault
-
- /**
- * @type {import('../../types/cache-interceptor.d.ts').default.CacheStore}
- */
- #store
-
- /**
- * @type {import('../../types/dispatcher.d.ts').default.DispatchHandler}
- */
- #handler
-
- /**
- * @type {import('node:stream').Writable | undefined}
- */
- #writeStream
-
- /**
- * @param {import('../../types/cache-interceptor.d.ts').default.CacheHandlerOptions} opts
- * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} cacheKey
- * @param {import('../../types/dispatcher.d.ts').default.DispatchHandler} handler
- */
- constructor ({ store, type, cacheByDefault }, cacheKey, handler) {
- this.#store = store
- this.#cacheType = type
- this.#cacheByDefault = cacheByDefault
- this.#cacheKey = cacheKey
- this.#handler = handler
- }
-
- onRequestStart (controller, context) {
- this.#writeStream?.destroy()
- this.#writeStream = undefined
- this.#handler.onRequestStart?.(controller, context)
- }
-
- onRequestUpgrade (controller, statusCode, headers, socket) {
- this.#handler.onRequestUpgrade?.(controller, statusCode, headers, socket)
- }
-
- /**
- * @param {import('../../types/dispatcher.d.ts').default.DispatchController} controller
- * @param {number} statusCode
- * @param {import('../../types/header.d.ts').IncomingHttpHeaders} resHeaders
- * @param {string} statusMessage
- */
- onResponseStart (
- controller,
- statusCode,
- resHeaders,
- statusMessage
- ) {
- const downstreamOnHeaders = () =>
- this.#handler.onResponseStart?.(
- controller,
- statusCode,
- resHeaders,
- statusMessage
- )
- const handler = this
-
- if (
- !util.safeHTTPMethods.includes(this.#cacheKey.method) &&
- statusCode >= 200 &&
- statusCode <= 399
- ) {
- // Successful response to an unsafe method, delete it from cache
- // https://www.rfc-editor.org/rfc/rfc9111.html#name-invalidating-stored-response
- try {
- this.#store.delete(this.#cacheKey)?.catch?.(noop)
- } catch {
- // Fail silently
- }
- return downstreamOnHeaders()
- }
-
- const cacheControlHeader = resHeaders['cache-control']
- const heuristicallyCacheable = resHeaders['last-modified'] && HEURISTICALLY_CACHEABLE_STATUS_CODES.includes(statusCode)
- if (
- !cacheControlHeader &&
- !resHeaders['expires'] &&
- !heuristicallyCacheable &&
- !this.#cacheByDefault
- ) {
- // Don't have anything to tell us this response is cachable and we're not
- // caching by default
- return downstreamOnHeaders()
- }
-
- const cacheControlDirectives = cacheControlHeader ? parseCacheControlHeader(cacheControlHeader) : {}
- if (!canCacheResponse(this.#cacheType, statusCode, resHeaders, cacheControlDirectives)) {
- return downstreamOnHeaders()
- }
-
- const now = Date.now()
- const resAge = resHeaders.age ? getAge(resHeaders.age) : undefined
- if (resAge && resAge >= MAX_RESPONSE_AGE) {
- // Response considered stale
- return downstreamOnHeaders()
- }
-
- const resDate = typeof resHeaders.date === 'string'
- ? parseHttpDate(resHeaders.date)
- : undefined
-
- const staleAt =
- determineStaleAt(this.#cacheType, now, resAge, resHeaders, resDate, cacheControlDirectives) ??
- this.#cacheByDefault
- if (staleAt === undefined || (resAge && resAge > staleAt)) {
- return downstreamOnHeaders()
- }
-
- const baseTime = resDate ? resDate.getTime() : now
- const absoluteStaleAt = staleAt + baseTime
- if (now >= absoluteStaleAt) {
- // Response is already stale
- return downstreamOnHeaders()
- }
-
- let varyDirectives
- if (this.#cacheKey.headers && resHeaders.vary) {
- varyDirectives = parseVaryHeader(resHeaders.vary, this.#cacheKey.headers)
- if (!varyDirectives) {
- // Parse error
- return downstreamOnHeaders()
- }
- }
-
- const deleteAt = determineDeleteAt(baseTime, cacheControlDirectives, absoluteStaleAt)
- const strippedHeaders = stripNecessaryHeaders(resHeaders, cacheControlDirectives)
-
- /**
- * @type {import('../../types/cache-interceptor.d.ts').default.CacheValue}
- */
- const value = {
- statusCode,
- statusMessage,
- headers: strippedHeaders,
- vary: varyDirectives,
- cacheControlDirectives,
- cachedAt: resAge ? now - resAge : now,
- staleAt: absoluteStaleAt,
- deleteAt
- }
-
- // Not modified, re-use the cached value
- // https://www.rfc-editor.org/rfc/rfc9111.html#name-handling-304-not-modified
- if (statusCode === 304) {
- const handle304 = (cachedValue) => {
- if (!cachedValue) {
- // Do not create a new cache entry, as a 304 won't have a body - so cannot be cached.
- return downstreamOnHeaders()
- }
-
- // Re-use the cached value: statuscode, statusmessage, headers and body
- value.statusCode = cachedValue.statusCode
- value.statusMessage = cachedValue.statusMessage
- value.etag = cachedValue.etag
- value.headers = { ...cachedValue.headers, ...strippedHeaders }
-
- downstreamOnHeaders()
-
- this.#writeStream = this.#store.createWriteStream(this.#cacheKey, value)
-
- if (!this.#writeStream || !cachedValue?.body) {
- return
- }
-
- if (typeof cachedValue.body.values === 'function') {
- const bodyIterator = cachedValue.body.values()
-
- const streamCachedBody = () => {
- for (const chunk of bodyIterator) {
- const full = this.#writeStream.write(chunk) === false
- this.#handler.onResponseData?.(controller, chunk)
- // when stream is full stop writing until we get a 'drain' event
- if (full) {
- break
- }
- }
- }
-
- this.#writeStream
- .on('error', function () {
- handler.#writeStream = undefined
- handler.#store.delete(handler.#cacheKey)
- })
- .on('drain', () => {
- streamCachedBody()
- })
- .on('close', function () {
- if (handler.#writeStream === this) {
- handler.#writeStream = undefined
- }
- })
-
- streamCachedBody()
- } else if (typeof cachedValue.body.on === 'function') {
- // Readable stream body (e.g. from async/remote cache stores)
- cachedValue.body
- .on('data', (chunk) => {
- this.#writeStream.write(chunk)
- this.#handler.onResponseData?.(controller, chunk)
- })
- .on('end', () => {
- this.#writeStream.end()
- })
- .on('error', () => {
- this.#writeStream = undefined
- this.#store.delete(this.#cacheKey)
- })
-
- this.#writeStream
- .on('error', function () {
- handler.#writeStream = undefined
- handler.#store.delete(handler.#cacheKey)
- })
- .on('close', function () {
- if (handler.#writeStream === this) {
- handler.#writeStream = undefined
- }
- })
- }
- }
-
- /**
- * @type {import('../../types/cache-interceptor.d.ts').default.CacheValue}
- */
- const result = this.#store.get(this.#cacheKey)
- if (result && typeof result.then === 'function') {
- result.then(handle304)
- } else {
- handle304(result)
- }
- } else {
- if (typeof resHeaders.etag === 'string' && isEtagUsable(resHeaders.etag)) {
- value.etag = resHeaders.etag
- }
-
- this.#writeStream = this.#store.createWriteStream(this.#cacheKey, value)
-
- if (!this.#writeStream) {
- return downstreamOnHeaders()
- }
-
- this.#writeStream
- .on('drain', () => controller.resume())
- .on('error', function () {
- // TODO (fix): Make error somehow observable?
- handler.#writeStream = undefined
-
- // Delete the value in case the cache store is holding onto state from
- // the call to createWriteStream
- handler.#store.delete(handler.#cacheKey)
- })
- .on('close', function () {
- if (handler.#writeStream === this) {
- handler.#writeStream = undefined
- }
-
- // TODO (fix): Should we resume even if was paused downstream?
- controller.resume()
- })
-
- downstreamOnHeaders()
- }
- }
-
- onResponseData (controller, chunk) {
- if (this.#writeStream?.write(chunk) === false) {
- controller.pause()
- }
-
- this.#handler.onResponseData?.(controller, chunk)
- }
-
- onResponseEnd (controller, trailers) {
- this.#writeStream?.end()
- this.#handler.onResponseEnd?.(controller, trailers)
- }
-
- onResponseError (controller, err) {
- this.#writeStream?.destroy(err)
- this.#writeStream = undefined
- this.#handler.onResponseError?.(controller, err)
- }
-}
-
-/**
- * @see https://www.rfc-editor.org/rfc/rfc9111.html#name-storing-responses-to-authen
- *
- * @param {import('../../types/cache-interceptor.d.ts').default.CacheOptions['type']} cacheType
- * @param {number} statusCode
- * @param {import('../../types/header.d.ts').IncomingHttpHeaders} resHeaders
- * @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives} cacheControlDirectives
- */
-function canCacheResponse (cacheType, statusCode, resHeaders, cacheControlDirectives) {
- // Status code must be final and understood.
- if (statusCode < 200 || NOT_UNDERSTOOD_STATUS_CODES.includes(statusCode)) {
- return false
- }
- // Responses with neither status codes that are heuristically cacheable, nor "explicit enough" caching
- // directives, are not cacheable. "Explicit enough": see https://www.rfc-editor.org/rfc/rfc9111.html#section-3
- if (!HEURISTICALLY_CACHEABLE_STATUS_CODES.includes(statusCode) && !resHeaders['expires'] &&
- !cacheControlDirectives.public &&
- cacheControlDirectives['max-age'] === undefined &&
- // RFC 9111: a private response directive, if the cache is not shared
- !(cacheControlDirectives.private && cacheType === 'private') &&
- !(cacheControlDirectives['s-maxage'] !== undefined && cacheType === 'shared')
- ) {
- return false
- }
-
- if (cacheControlDirectives['no-store']) {
- return false
- }
-
- if (cacheType === 'shared' && cacheControlDirectives.private === true) {
- return false
- }
-
- // https://www.rfc-editor.org/rfc/rfc9111.html#section-4.1-5
- if (resHeaders.vary?.includes('*')) {
- return false
- }
-
- // https://www.rfc-editor.org/rfc/rfc9111.html#name-storing-responses-to-authen
- if (resHeaders.authorization) {
- if (!cacheControlDirectives.public || typeof resHeaders.authorization !== 'string') {
- return false
- }
-
- if (
- Array.isArray(cacheControlDirectives['no-cache']) &&
- cacheControlDirectives['no-cache'].includes('authorization')
- ) {
- return false
- }
-
- if (
- Array.isArray(cacheControlDirectives['private']) &&
- cacheControlDirectives['private'].includes('authorization')
- ) {
- return false
- }
- }
-
- return true
-}
-
-/**
- * @param {string | string[]} ageHeader
- * @returns {number | undefined}
- */
-function getAge (ageHeader) {
- const age = parseInt(Array.isArray(ageHeader) ? ageHeader[0] : ageHeader)
-
- return isNaN(age) ? undefined : age * 1000
-}
-
-/**
- * @param {import('../../types/cache-interceptor.d.ts').default.CacheOptions['type']} cacheType
- * @param {number} now
- * @param {number | undefined} age
- * @param {import('../../types/header.d.ts').IncomingHttpHeaders} resHeaders
- * @param {Date | undefined} responseDate
- * @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives} cacheControlDirectives
- *
- * @returns {number | undefined} time that the value is stale at in seconds or undefined if it shouldn't be cached
- */
-function determineStaleAt (cacheType, now, age, resHeaders, responseDate, cacheControlDirectives) {
- if (cacheType === 'shared') {
- // Prioritize s-maxage since we're a shared cache
- // s-maxage > max-age > Expire
- // https://www.rfc-editor.org/rfc/rfc9111.html#section-5.2.2.10-3
- const sMaxAge = cacheControlDirectives['s-maxage']
- if (sMaxAge !== undefined) {
- return sMaxAge > 0 ? sMaxAge * 1000 : undefined
- }
- }
-
- const maxAge = cacheControlDirectives['max-age']
- if (maxAge !== undefined) {
- return maxAge > 0 ? maxAge * 1000 : undefined
- }
-
- if (typeof resHeaders.expires === 'string') {
- // https://www.rfc-editor.org/rfc/rfc9111.html#section-5.3
- const expiresDate = parseHttpDate(resHeaders.expires)
- if (expiresDate) {
- if (now >= expiresDate.getTime()) {
- return undefined
- }
-
- if (responseDate) {
- if (responseDate >= expiresDate) {
- return undefined
- }
-
- if (age !== undefined && age > (expiresDate - responseDate)) {
- return undefined
- }
- }
-
- return expiresDate.getTime() - now
- }
- }
-
- if (typeof resHeaders['last-modified'] === 'string') {
- // https://www.rfc-editor.org/rfc/rfc9111.html#name-calculating-heuristic-fresh
- const lastModified = new Date(resHeaders['last-modified'])
- if (isValidDate(lastModified)) {
- if (lastModified.getTime() >= now) {
- return undefined
- }
-
- const responseAge = now - lastModified.getTime()
-
- return responseAge * 0.1
- }
- }
-
- if (cacheControlDirectives.immutable) {
- // https://www.rfc-editor.org/rfc/rfc8246.html#section-2.2
- return 31536000
- }
-
- return undefined
-}
-
-/**
- * @param {number} now
- * @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives} cacheControlDirectives
- * @param {number} staleAt
- */
-function determineDeleteAt (now, cacheControlDirectives, staleAt) {
- let staleWhileRevalidate = -Infinity
- let staleIfError = -Infinity
- let immutable = -Infinity
-
- if (cacheControlDirectives['stale-while-revalidate']) {
- staleWhileRevalidate = staleAt + (cacheControlDirectives['stale-while-revalidate'] * 1000)
- }
-
- if (cacheControlDirectives['stale-if-error']) {
- staleIfError = staleAt + (cacheControlDirectives['stale-if-error'] * 1000)
- }
-
- if (staleWhileRevalidate === -Infinity && staleIfError === -Infinity) {
- immutable = now + 31536000000
- }
-
- return Math.max(staleAt, staleWhileRevalidate, staleIfError, immutable)
-}
-
-/**
- * Strips headers required to be removed in cached responses
- * @param {import('../../types/header.d.ts').IncomingHttpHeaders} resHeaders
- * @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives} cacheControlDirectives
- * @returns {Record<string, string | string []>}
- */
-function stripNecessaryHeaders (resHeaders, cacheControlDirectives) {
- const headersToRemove = [
- 'connection',
- 'proxy-authenticate',
- 'proxy-authentication-info',
- 'proxy-authorization',
- 'proxy-connection',
- 'te',
- 'transfer-encoding',
- 'upgrade',
- // We'll add age back when serving it
- 'age'
- ]
-
- if (resHeaders['connection']) {
- if (Array.isArray(resHeaders['connection'])) {
- // connection: a
- // connection: b
- headersToRemove.push(...resHeaders['connection'].map(header => header.trim()))
- } else {
- // connection: a, b
- headersToRemove.push(...resHeaders['connection'].split(',').map(header => header.trim()))
- }
- }
-
- if (Array.isArray(cacheControlDirectives['no-cache'])) {
- headersToRemove.push(...cacheControlDirectives['no-cache'])
- }
-
- if (Array.isArray(cacheControlDirectives['private'])) {
- headersToRemove.push(...cacheControlDirectives['private'])
- }
-
- let strippedHeaders
- for (const headerName of headersToRemove) {
- if (resHeaders[headerName]) {
- strippedHeaders ??= { ...resHeaders }
- delete strippedHeaders[headerName]
- }
- }
-
- return strippedHeaders ?? resHeaders
-}
-
-/**
- * @param {Date} date
- * @returns {boolean}
- */
-function isValidDate (date) {
- return date instanceof Date && Number.isFinite(date.valueOf())
-}
-
-module.exports = CacheHandler
diff --git a/vanilla/node_modules/undici/lib/handler/cache-revalidation-handler.js b/vanilla/node_modules/undici/lib/handler/cache-revalidation-handler.js
deleted file mode 100644
index 393d16d..0000000
--- a/vanilla/node_modules/undici/lib/handler/cache-revalidation-handler.js
+++ /dev/null
@@ -1,124 +0,0 @@
-'use strict'
-
-const assert = require('node:assert')
-
-/**
- * This takes care of revalidation requests we send to the origin. If we get
- * a response indicating that what we have is cached (via a HTTP 304), we can
- * continue using the cached value. Otherwise, we'll receive the new response
- * here, which we then just pass on to the next handler (most likely a
- * CacheHandler). Note that this assumes the proper headers were already
- * included in the request to tell the origin that we want to revalidate the
- * response (i.e. if-modified-since or if-none-match).
- *
- * @see https://www.rfc-editor.org/rfc/rfc9111.html#name-validation
- *
- * @implements {import('../../types/dispatcher.d.ts').default.DispatchHandler}
- */
-class CacheRevalidationHandler {
- #successful = false
-
- /**
- * @type {((boolean, any) => void) | null}
- */
- #callback
-
- /**
- * @type {(import('../../types/dispatcher.d.ts').default.DispatchHandler)}
- */
- #handler
-
- #context
-
- /**
- * @type {boolean}
- */
- #allowErrorStatusCodes
-
- /**
- * @param {(boolean) => void} callback Function to call if the cached value is valid
- * @param {import('../../types/dispatcher.d.ts').default.DispatchHandlers} handler
- * @param {boolean} allowErrorStatusCodes
- */
- constructor (callback, handler, allowErrorStatusCodes) {
- if (typeof callback !== 'function') {
- throw new TypeError('callback must be a function')
- }
-
- this.#callback = callback
- this.#handler = handler
- this.#allowErrorStatusCodes = allowErrorStatusCodes
- }
-
- onRequestStart (_, context) {
- this.#successful = false
- this.#context = context
- }
-
- onRequestUpgrade (controller, statusCode, headers, socket) {
- this.#handler.onRequestUpgrade?.(controller, statusCode, headers, socket)
- }
-
- onResponseStart (
- controller,
- statusCode,
- headers,
- statusMessage
- ) {
- assert(this.#callback != null)
-
- // https://www.rfc-editor.org/rfc/rfc9111.html#name-handling-a-validation-respo
- // https://datatracker.ietf.org/doc/html/rfc5861#section-4
- this.#successful = statusCode === 304 ||
- (this.#allowErrorStatusCodes && statusCode >= 500 && statusCode <= 504)
- this.#callback(this.#successful, this.#context)
- this.#callback = null
-
- if (this.#successful) {
- return true
- }
-
- this.#handler.onRequestStart?.(controller, this.#context)
- this.#handler.onResponseStart?.(
- controller,
- statusCode,
- headers,
- statusMessage
- )
- }
-
- onResponseData (controller, chunk) {
- if (this.#successful) {
- return
- }
-
- return this.#handler.onResponseData?.(controller, chunk)
- }
-
- onResponseEnd (controller, trailers) {
- if (this.#successful) {
- return
- }
-
- this.#handler.onResponseEnd?.(controller, trailers)
- }
-
- onResponseError (controller, err) {
- if (this.#successful) {
- return
- }
-
- if (this.#callback) {
- this.#callback(false)
- this.#callback = null
- }
-
- if (typeof this.#handler.onResponseError === 'function') {
- this.#handler.onResponseError(controller, err)
- } else {
- throw err
- }
- }
-}
-
-module.exports = CacheRevalidationHandler
diff --git a/vanilla/node_modules/undici/lib/handler/decorator-handler.js b/vanilla/node_modules/undici/lib/handler/decorator-handler.js
deleted file mode 100644
index 50fbb0c..0000000
--- a/vanilla/node_modules/undici/lib/handler/decorator-handler.js
+++ /dev/null
@@ -1,67 +0,0 @@
-'use strict'
-
-const assert = require('node:assert')
-const WrapHandler = require('./wrap-handler')
-
-/**
- * @deprecated
- */
-module.exports = class DecoratorHandler {
- #handler
- #onCompleteCalled = false
- #onErrorCalled = false
- #onResponseStartCalled = false
-
- constructor (handler) {
- if (typeof handler !== 'object' || handler === null) {
- throw new TypeError('handler must be an object')
- }
- this.#handler = WrapHandler.wrap(handler)
- }
-
- onRequestStart (...args) {
- this.#handler.onRequestStart?.(...args)
- }
-
- onRequestUpgrade (...args) {
- assert(!this.#onCompleteCalled)
- assert(!this.#onErrorCalled)
-
- return this.#handler.onRequestUpgrade?.(...args)
- }
-
- onResponseStart (...args) {
- assert(!this.#onCompleteCalled)
- assert(!this.#onErrorCalled)
- assert(!this.#onResponseStartCalled)
-
- this.#onResponseStartCalled = true
-
- return this.#handler.onResponseStart?.(...args)
- }
-
- onResponseData (...args) {
- assert(!this.#onCompleteCalled)
- assert(!this.#onErrorCalled)
-
- return this.#handler.onResponseData?.(...args)
- }
-
- onResponseEnd (...args) {
- assert(!this.#onCompleteCalled)
- assert(!this.#onErrorCalled)
-
- this.#onCompleteCalled = true
- return this.#handler.onResponseEnd?.(...args)
- }
-
- onResponseError (...args) {
- this.#onErrorCalled = true
- return this.#handler.onResponseError?.(...args)
- }
-
- /**
- * @deprecated
- */
- onBodySent () {}
-}
diff --git a/vanilla/node_modules/undici/lib/handler/deduplication-handler.js b/vanilla/node_modules/undici/lib/handler/deduplication-handler.js
deleted file mode 100644
index 33a2c4f..0000000
--- a/vanilla/node_modules/undici/lib/handler/deduplication-handler.js
+++ /dev/null
@@ -1,216 +0,0 @@
-'use strict'
-
-/**
- * @typedef {import('../../types/dispatcher.d.ts').default.DispatchHandler} DispatchHandler
- */
-
-/**
- * Handler that buffers response data and notifies multiple waiting handlers.
- * Used for request deduplication.
- *
- * @implements {DispatchHandler}
- */
-class DeduplicationHandler {
- /**
- * @type {DispatchHandler}
- */
- #primaryHandler
-
- /**
- * @type {DispatchHandler[]}
- */
- #waitingHandlers = []
-
- /**
- * @type {Buffer[]}
- */
- #chunks = []
-
- /**
- * @type {number}
- */
- #statusCode = 0
-
- /**
- * @type {Record<string, string | string[]>}
- */
- #headers = {}
-
- /**
- * @type {string}
- */
- #statusMessage = ''
-
- /**
- * @type {boolean}
- */
- #aborted = false
-
- /**
- * @type {import('../../types/dispatcher.d.ts').default.DispatchController | null}
- */
- #controller = null
-
- /**
- * @type {(() => void) | null}
- */
- #onComplete = null
-
- /**
- * @param {DispatchHandler} primaryHandler The primary handler
- * @param {() => void} onComplete Callback when request completes
- */
- constructor (primaryHandler, onComplete) {
- this.#primaryHandler = primaryHandler
- this.#onComplete = onComplete
- }
-
- /**
- * Add a waiting handler that will receive the buffered response
- * @param {DispatchHandler} handler
- */
- addWaitingHandler (handler) {
- this.#waitingHandlers.push(handler)
- }
-
- /**
- * @param {() => void} abort
- * @param {any} context
- */
- onRequestStart (controller, context) {
- this.#controller = controller
- this.#primaryHandler.onRequestStart?.(controller, context)
- }
-
- /**
- * @param {import('../../types/dispatcher.d.ts').default.DispatchController} controller
- * @param {number} statusCode
- * @param {import('../../types/header.d.ts').IncomingHttpHeaders} headers
- * @param {Socket} socket
- */
- onRequestUpgrade (controller, statusCode, headers, socket) {
- this.#primaryHandler.onRequestUpgrade?.(controller, statusCode, headers, socket)
- }
-
- /**
- * @param {import('../../types/dispatcher.d.ts').default.DispatchController} controller
- * @param {number} statusCode
- * @param {Record<string, string | string[]>} headers
- * @param {string} statusMessage
- */
- onResponseStart (controller, statusCode, headers, statusMessage) {
- this.#statusCode = statusCode
- this.#headers = headers
- this.#statusMessage = statusMessage
- this.#primaryHandler.onResponseStart?.(controller, statusCode, headers, statusMessage)
- }
-
- /**
- * @param {import('../../types/dispatcher.d.ts').default.DispatchController} controller
- * @param {Buffer} chunk
- */
- onResponseData (controller, chunk) {
- // Buffer the chunk for waiting handlers
- this.#chunks.push(Buffer.from(chunk))
- this.#primaryHandler.onResponseData?.(controller, chunk)
- }
-
- /**
- * @param {import('../../types/dispatcher.d.ts').default.DispatchController} controller
- * @param {object} trailers
- */
- onResponseEnd (controller, trailers) {
- this.#primaryHandler.onResponseEnd?.(controller, trailers)
- this.#notifyWaitingHandlers()
- this.#onComplete?.()
- }
-
- /**
- * @param {import('../../types/dispatcher.d.ts').default.DispatchController} controller
- * @param {Error} err
- */
- onResponseError (controller, err) {
- this.#aborted = true
- this.#primaryHandler.onResponseError?.(controller, err)
- this.#notifyWaitingHandlersError(err)
- this.#onComplete?.()
- }
-
- /**
- * Notify all waiting handlers with the buffered response
- */
- #notifyWaitingHandlers () {
- const body = Buffer.concat(this.#chunks)
-
- for (const handler of this.#waitingHandlers) {
- // Create a simple controller for each waiting handler
- const waitingController = {
- resume () {},
- pause () {},
- get paused () { return false },
- get aborted () { return false },
- get reason () { return null },
- abort () {}
- }
-
- try {
- handler.onRequestStart?.(waitingController, null)
-
- if (waitingController.aborted) {
- continue
- }
-
- handler.onResponseStart?.(
- waitingController,
- this.#statusCode,
- this.#headers,
- this.#statusMessage
- )
-
- if (waitingController.aborted) {
- continue
- }
-
- if (body.length > 0) {
- handler.onResponseData?.(waitingController, body)
- }
-
- handler.onResponseEnd?.(waitingController, {})
- } catch {
- // Ignore errors from waiting handlers
- }
- }
-
- this.#waitingHandlers = []
- this.#chunks = []
- }
-
- /**
- * Notify all waiting handlers of an error
- * @param {Error} err
- */
- #notifyWaitingHandlersError (err) {
- for (const handler of this.#waitingHandlers) {
- const waitingController = {
- resume () {},
- pause () {},
- get paused () { return false },
- get aborted () { return true },
- get reason () { return err },
- abort () {}
- }
-
- try {
- handler.onRequestStart?.(waitingController, null)
- handler.onResponseError?.(waitingController, err)
- } catch {
- // Ignore errors from waiting handlers
- }
- }
-
- this.#waitingHandlers = []
- this.#chunks = []
- }
-}
-
-module.exports = DeduplicationHandler
diff --git a/vanilla/node_modules/undici/lib/handler/redirect-handler.js b/vanilla/node_modules/undici/lib/handler/redirect-handler.js
deleted file mode 100644
index dd0f471..0000000
--- a/vanilla/node_modules/undici/lib/handler/redirect-handler.js
+++ /dev/null
@@ -1,237 +0,0 @@
-'use strict'
-
-const util = require('../core/util')
-const { kBodyUsed } = require('../core/symbols')
-const assert = require('node:assert')
-const { InvalidArgumentError } = require('../core/errors')
-const EE = require('node:events')
-
-const redirectableStatusCodes = [300, 301, 302, 303, 307, 308]
-
-const kBody = Symbol('body')
-
-const noop = () => {}
-
-class BodyAsyncIterable {
- constructor (body) {
- this[kBody] = body
- this[kBodyUsed] = false
- }
-
- async * [Symbol.asyncIterator] () {
- assert(!this[kBodyUsed], 'disturbed')
- this[kBodyUsed] = true
- yield * this[kBody]
- }
-}
-
-class RedirectHandler {
- static buildDispatch (dispatcher, maxRedirections) {
- if (maxRedirections != null && (!Number.isInteger(maxRedirections) || maxRedirections < 0)) {
- throw new InvalidArgumentError('maxRedirections must be a positive number')
- }
-
- const dispatch = dispatcher.dispatch.bind(dispatcher)
- return (opts, originalHandler) => dispatch(opts, new RedirectHandler(dispatch, maxRedirections, opts, originalHandler))
- }
-
- constructor (dispatch, maxRedirections, opts, handler) {
- if (maxRedirections != null && (!Number.isInteger(maxRedirections) || maxRedirections < 0)) {
- throw new InvalidArgumentError('maxRedirections must be a positive number')
- }
-
- this.dispatch = dispatch
- this.location = null
- const { maxRedirections: _, ...cleanOpts } = opts
- this.opts = cleanOpts // opts must be a copy, exclude maxRedirections
- this.maxRedirections = maxRedirections
- this.handler = handler
- this.history = []
-
- if (util.isStream(this.opts.body)) {
- // TODO (fix): Provide some way for the user to cache the file to e.g. /tmp
- // so that it can be dispatched again?
- // TODO (fix): Do we need 100-expect support to provide a way to do this properly?
- if (util.bodyLength(this.opts.body) === 0) {
- this.opts.body
- .on('data', function () {
- assert(false)
- })
- }
-
- if (typeof this.opts.body.readableDidRead !== 'boolean') {
- this.opts.body[kBodyUsed] = false
- EE.prototype.on.call(this.opts.body, 'data', function () {
- this[kBodyUsed] = true
- })
- }
- } else if (this.opts.body && typeof this.opts.body.pipeTo === 'function') {
- // TODO (fix): We can't access ReadableStream internal state
- // to determine whether or not it has been disturbed. This is just
- // a workaround.
- this.opts.body = new BodyAsyncIterable(this.opts.body)
- } else if (
- this.opts.body &&
- typeof this.opts.body !== 'string' &&
- !ArrayBuffer.isView(this.opts.body) &&
- util.isIterable(this.opts.body) &&
- !util.isFormDataLike(this.opts.body)
- ) {
- // TODO: Should we allow re-using iterable if !this.opts.idempotent
- // or through some other flag?
- this.opts.body = new BodyAsyncIterable(this.opts.body)
- }
- }
-
- onRequestStart (controller, context) {
- this.handler.onRequestStart?.(controller, { ...context, history: this.history })
- }
-
- onRequestUpgrade (controller, statusCode, headers, socket) {
- this.handler.onRequestUpgrade?.(controller, statusCode, headers, socket)
- }
-
- onResponseStart (controller, statusCode, headers, statusMessage) {
- if (this.opts.throwOnMaxRedirect && this.history.length >= this.maxRedirections) {
- throw new Error('max redirects')
- }
-
- // https://tools.ietf.org/html/rfc7231#section-6.4.2
- // https://fetch.spec.whatwg.org/#http-redirect-fetch
- // In case of HTTP 301 or 302 with POST, change the method to GET
- if ((statusCode === 301 || statusCode === 302) && this.opts.method === 'POST') {
- this.opts.method = 'GET'
- if (util.isStream(this.opts.body)) {
- util.destroy(this.opts.body.on('error', noop))
- }
- this.opts.body = null
- }
-
- // https://tools.ietf.org/html/rfc7231#section-6.4.4
- // In case of HTTP 303, always replace method to be either HEAD or GET
- if (statusCode === 303 && this.opts.method !== 'HEAD') {
- this.opts.method = 'GET'
- if (util.isStream(this.opts.body)) {
- util.destroy(this.opts.body.on('error', noop))
- }
- this.opts.body = null
- }
-
- this.location = this.history.length >= this.maxRedirections || util.isDisturbed(this.opts.body) || redirectableStatusCodes.indexOf(statusCode) === -1
- ? null
- : headers.location
-
- if (this.opts.origin) {
- this.history.push(new URL(this.opts.path, this.opts.origin))
- }
-
- if (!this.location) {
- this.handler.onResponseStart?.(controller, statusCode, headers, statusMessage)
- return
- }
-
- const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin)))
- const path = search ? `${pathname}${search}` : pathname
-
- // Check for redirect loops by seeing if we've already visited this URL in our history
- // This catches the case where Client/Pool try to handle cross-origin redirects but fail
- // and keep redirecting to the same URL in an infinite loop
- const redirectUrlString = `${origin}${path}`
- for (const historyUrl of this.history) {
- if (historyUrl.toString() === redirectUrlString) {
- throw new InvalidArgumentError(`Redirect loop detected. Cannot redirect to ${origin}. This typically happens when using a Client or Pool with cross-origin redirects. Use an Agent for cross-origin redirects.`)
- }
- }
-
- // Remove headers referring to the original URL.
- // By default it is Host only, unless it's a 303 (see below), which removes also all Content-* headers.
- // https://tools.ietf.org/html/rfc7231#section-6.4
- this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin)
- this.opts.path = path
- this.opts.origin = origin
- this.opts.query = null
- }
-
- onResponseData (controller, chunk) {
- if (this.location) {
- /*
- https://tools.ietf.org/html/rfc7231#section-6.4
-
- TLDR: undici always ignores 3xx response bodies.
-
- Redirection is used to serve the requested resource from another URL, so it assumes that
- no body is generated (and thus can be ignored). Even though generating a body is not prohibited.
-
- For status 301, 302, 303, 307 and 308 (the latter from RFC 7238), the specs mention that the body usually
- (which means it's optional and not mandated) contain just an hyperlink to the value of
- the Location response header, so the body can be ignored safely.
-
- For status 300, which is "Multiple Choices", the spec mentions both generating a Location
- response header AND a response body with the other possible location to follow.
- Since the spec explicitly chooses not to specify a format for such body and leave it to
- servers and browsers implementors, we ignore the body as there is no specified way to eventually parse it.
- */
- } else {
- this.handler.onResponseData?.(controller, chunk)
- }
- }
-
- onResponseEnd (controller, trailers) {
- if (this.location) {
- /*
- https://tools.ietf.org/html/rfc7231#section-6.4
-
- TLDR: undici always ignores 3xx response trailers as they are not expected in case of redirections
- and neither are useful if present.
-
- See comment on onData method above for more detailed information.
- */
- this.dispatch(this.opts, this)
- } else {
- this.handler.onResponseEnd(controller, trailers)
- }
- }
-
- onResponseError (controller, error) {
- this.handler.onResponseError?.(controller, error)
- }
-}
-
-// https://tools.ietf.org/html/rfc7231#section-6.4.4
-function shouldRemoveHeader (header, removeContent, unknownOrigin) {
- if (header.length === 4) {
- return util.headerNameToString(header) === 'host'
- }
- if (removeContent && util.headerNameToString(header).startsWith('content-')) {
- return true
- }
- if (unknownOrigin && (header.length === 13 || header.length === 6 || header.length === 19)) {
- const name = util.headerNameToString(header)
- return name === 'authorization' || name === 'cookie' || name === 'proxy-authorization'
- }
- return false
-}
-
-// https://tools.ietf.org/html/rfc7231#section-6.4
-function cleanRequestHeaders (headers, removeContent, unknownOrigin) {
- const ret = []
- if (Array.isArray(headers)) {
- for (let i = 0; i < headers.length; i += 2) {
- if (!shouldRemoveHeader(headers[i], removeContent, unknownOrigin)) {
- ret.push(headers[i], headers[i + 1])
- }
- }
- } else if (headers && typeof headers === 'object') {
- const entries = typeof headers[Symbol.iterator] === 'function' ? headers : Object.entries(headers)
- for (const [key, value] of entries) {
- if (!shouldRemoveHeader(key, removeContent, unknownOrigin)) {
- ret.push(key, value)
- }
- }
- } else {
- assert(headers == null, 'headers must be an object or an array')
- }
- return ret
-}
-
-module.exports = RedirectHandler
diff --git a/vanilla/node_modules/undici/lib/handler/retry-handler.js b/vanilla/node_modules/undici/lib/handler/retry-handler.js
deleted file mode 100644
index 1cbc789..0000000
--- a/vanilla/node_modules/undici/lib/handler/retry-handler.js
+++ /dev/null
@@ -1,394 +0,0 @@
-'use strict'
-const assert = require('node:assert')
-
-const { kRetryHandlerDefaultRetry } = require('../core/symbols')
-const { RequestRetryError } = require('../core/errors')
-const WrapHandler = require('./wrap-handler')
-const {
- isDisturbed,
- parseRangeHeader,
- wrapRequestBody
-} = require('../core/util')
-
-function calculateRetryAfterHeader (retryAfter) {
- const retryTime = new Date(retryAfter).getTime()
- return isNaN(retryTime) ? 0 : retryTime - Date.now()
-}
-
-class RetryHandler {
- constructor (opts, { dispatch, handler }) {
- const { retryOptions, ...dispatchOpts } = opts
- const {
- // Retry scoped
- retry: retryFn,
- maxRetries,
- maxTimeout,
- minTimeout,
- timeoutFactor,
- // Response scoped
- methods,
- errorCodes,
- retryAfter,
- statusCodes,
- throwOnError
- } = retryOptions ?? {}
-
- this.error = null
- this.dispatch = dispatch
- this.handler = WrapHandler.wrap(handler)
- this.opts = { ...dispatchOpts, body: wrapRequestBody(opts.body) }
- this.retryOpts = {
- throwOnError: throwOnError ?? true,
- retry: retryFn ?? RetryHandler[kRetryHandlerDefaultRetry],
- retryAfter: retryAfter ?? true,
- maxTimeout: maxTimeout ?? 30 * 1000, // 30s,
- minTimeout: minTimeout ?? 500, // .5s
- timeoutFactor: timeoutFactor ?? 2,
- maxRetries: maxRetries ?? 5,
- // What errors we should retry
- methods: methods ?? ['GET', 'HEAD', 'OPTIONS', 'PUT', 'DELETE', 'TRACE'],
- // Indicates which errors to retry
- statusCodes: statusCodes ?? [500, 502, 503, 504, 429],
- // List of errors to retry
- errorCodes: errorCodes ?? [
- 'ECONNRESET',
- 'ECONNREFUSED',
- 'ENOTFOUND',
- 'ENETDOWN',
- 'ENETUNREACH',
- 'EHOSTDOWN',
- 'EHOSTUNREACH',
- 'EPIPE',
- 'UND_ERR_SOCKET'
- ]
- }
-
- this.retryCount = 0
- this.retryCountCheckpoint = 0
- this.headersSent = false
- this.start = 0
- this.end = null
- this.etag = null
- }
-
- onResponseStartWithRetry (controller, statusCode, headers, statusMessage, err) {
- if (this.retryOpts.throwOnError) {
- // Preserve old behavior for status codes that are not eligible for retry
- if (this.retryOpts.statusCodes.includes(statusCode) === false) {
- this.headersSent = true
- this.handler.onResponseStart?.(controller, statusCode, headers, statusMessage)
- } else {
- this.error = err
- }
-
- return
- }
-
- if (isDisturbed(this.opts.body)) {
- this.headersSent = true
- this.handler.onResponseStart?.(controller, statusCode, headers, statusMessage)
- return
- }
-
- function shouldRetry (passedErr) {
- if (passedErr) {
- this.headersSent = true
- this.handler.onResponseStart?.(controller, statusCode, headers, statusMessage)
- controller.resume()
- return
- }
-
- this.error = err
- controller.resume()
- }
-
- controller.pause()
- this.retryOpts.retry(
- err,
- {
- state: { counter: this.retryCount },
- opts: { retryOptions: this.retryOpts, ...this.opts }
- },
- shouldRetry.bind(this)
- )
- }
-
- onRequestStart (controller, context) {
- if (!this.headersSent) {
- this.handler.onRequestStart?.(controller, context)
- }
- }
-
- onRequestUpgrade (controller, statusCode, headers, socket) {
- this.handler.onRequestUpgrade?.(controller, statusCode, headers, socket)
- }
-
- static [kRetryHandlerDefaultRetry] (err, { state, opts }, cb) {
- const { statusCode, code, headers } = err
- const { method, retryOptions } = opts
- const {
- maxRetries,
- minTimeout,
- maxTimeout,
- timeoutFactor,
- statusCodes,
- errorCodes,
- methods
- } = retryOptions
- const { counter } = state
-
- // Any code that is not a Undici's originated and allowed to retry
- if (code && code !== 'UND_ERR_REQ_RETRY' && !errorCodes.includes(code)) {
- cb(err)
- return
- }
-
- // If a set of method are provided and the current method is not in the list
- if (Array.isArray(methods) && !methods.includes(method)) {
- cb(err)
- return
- }
-
- // If a set of status code are provided and the current status code is not in the list
- if (
- statusCode != null &&
- Array.isArray(statusCodes) &&
- !statusCodes.includes(statusCode)
- ) {
- cb(err)
- return
- }
-
- // If we reached the max number of retries
- if (counter > maxRetries) {
- cb(err)
- return
- }
-
- let retryAfterHeader = headers?.['retry-after']
- if (retryAfterHeader) {
- retryAfterHeader = Number(retryAfterHeader)
- retryAfterHeader = Number.isNaN(retryAfterHeader)
- ? calculateRetryAfterHeader(headers['retry-after'])
- : retryAfterHeader * 1e3 // Retry-After is in seconds
- }
-
- const retryTimeout =
- retryAfterHeader > 0
- ? Math.min(retryAfterHeader, maxTimeout)
- : Math.min(minTimeout * timeoutFactor ** (counter - 1), maxTimeout)
-
- setTimeout(() => cb(null), retryTimeout)
- }
-
- onResponseStart (controller, statusCode, headers, statusMessage) {
- this.error = null
- this.retryCount += 1
-
- if (statusCode >= 300) {
- const err = new RequestRetryError('Request failed', statusCode, {
- headers,
- data: {
- count: this.retryCount
- }
- })
-
- this.onResponseStartWithRetry(controller, statusCode, headers, statusMessage, err)
- return
- }
-
- // Checkpoint for resume from where we left it
- if (this.headersSent) {
- // Only Partial Content 206 supposed to provide Content-Range,
- // any other status code that partially consumed the payload
- // should not be retried because it would result in downstream
- // wrongly concatenate multiple responses.
- if (statusCode !== 206 && (this.start > 0 || statusCode !== 200)) {
- throw new RequestRetryError('server does not support the range header and the payload was partially consumed', statusCode, {
- headers,
- data: { count: this.retryCount }
- })
- }
-
- const contentRange = parseRangeHeader(headers['content-range'])
- // If no content range
- if (!contentRange) {
- // We always throw here as we want to indicate that we entred unexpected path
- throw new RequestRetryError('Content-Range mismatch', statusCode, {
- headers,
- data: { count: this.retryCount }
- })
- }
-
- // Let's start with a weak etag check
- if (this.etag != null && this.etag !== headers.etag) {
- // We always throw here as we want to indicate that we entred unexpected path
- throw new RequestRetryError('ETag mismatch', statusCode, {
- headers,
- data: { count: this.retryCount }
- })
- }
-
- const { start, size, end = size ? size - 1 : null } = contentRange
-
- assert(this.start === start, 'content-range mismatch')
- assert(this.end == null || this.end === end, 'content-range mismatch')
-
- return
- }
-
- if (this.end == null) {
- if (statusCode === 206) {
- // First time we receive 206
- const range = parseRangeHeader(headers['content-range'])
-
- if (range == null) {
- this.headersSent = true
- this.handler.onResponseStart?.(
- controller,
- statusCode,
- headers,
- statusMessage
- )
- return
- }
-
- const { start, size, end = size ? size - 1 : null } = range
- assert(
- start != null && Number.isFinite(start),
- 'content-range mismatch'
- )
- assert(end != null && Number.isFinite(end), 'invalid content-length')
-
- this.start = start
- this.end = end
- }
-
- // We make our best to checkpoint the body for further range headers
- if (this.end == null) {
- const contentLength = headers['content-length']
- this.end = contentLength != null ? Number(contentLength) - 1 : null
- }
-
- assert(Number.isFinite(this.start))
- assert(
- this.end == null || Number.isFinite(this.end),
- 'invalid content-length'
- )
-
- this.resume = true
- this.etag = headers.etag != null ? headers.etag : null
-
- // Weak etags are not useful for comparison nor cache
- // for instance not safe to assume if the response is byte-per-byte
- // equal
- if (
- this.etag != null &&
- this.etag[0] === 'W' &&
- this.etag[1] === '/'
- ) {
- this.etag = null
- }
-
- this.headersSent = true
- this.handler.onResponseStart?.(
- controller,
- statusCode,
- headers,
- statusMessage
- )
- } else {
- throw new RequestRetryError('Request failed', statusCode, {
- headers,
- data: { count: this.retryCount }
- })
- }
- }
-
- onResponseData (controller, chunk) {
- if (this.error) {
- return
- }
-
- this.start += chunk.length
-
- this.handler.onResponseData?.(controller, chunk)
- }
-
- onResponseEnd (controller, trailers) {
- if (this.error && this.retryOpts.throwOnError) {
- throw this.error
- }
-
- if (!this.error) {
- this.retryCount = 0
- return this.handler.onResponseEnd?.(controller, trailers)
- }
-
- this.retry(controller)
- }
-
- retry (controller) {
- if (this.start !== 0) {
- const headers = { range: `bytes=${this.start}-${this.end ?? ''}` }
-
- // Weak etag check - weak etags will make comparison algorithms never match
- if (this.etag != null) {
- headers['if-match'] = this.etag
- }
-
- this.opts = {
- ...this.opts,
- headers: {
- ...this.opts.headers,
- ...headers
- }
- }
- }
-
- try {
- this.retryCountCheckpoint = this.retryCount
- this.dispatch(this.opts, this)
- } catch (err) {
- this.handler.onResponseError?.(controller, err)
- }
- }
-
- onResponseError (controller, err) {
- if (controller?.aborted || isDisturbed(this.opts.body)) {
- this.handler.onResponseError?.(controller, err)
- return
- }
-
- function shouldRetry (returnedErr) {
- if (!returnedErr) {
- this.retry(controller)
- return
- }
-
- this.handler?.onResponseError?.(controller, returnedErr)
- }
-
- // We reconcile in case of a mix between network errors
- // and server error response
- if (this.retryCount - this.retryCountCheckpoint > 0) {
- // We count the difference between the last checkpoint and the current retry count
- this.retryCount =
- this.retryCountCheckpoint +
- (this.retryCount - this.retryCountCheckpoint)
- } else {
- this.retryCount += 1
- }
-
- this.retryOpts.retry(
- err,
- {
- state: { counter: this.retryCount },
- opts: { retryOptions: this.retryOpts, ...this.opts }
- },
- shouldRetry.bind(this)
- )
- }
-}
-
-module.exports = RetryHandler
diff --git a/vanilla/node_modules/undici/lib/handler/unwrap-handler.js b/vanilla/node_modules/undici/lib/handler/unwrap-handler.js
deleted file mode 100644
index 865593a..0000000
--- a/vanilla/node_modules/undici/lib/handler/unwrap-handler.js
+++ /dev/null
@@ -1,96 +0,0 @@
-'use strict'
-
-const { parseHeaders } = require('../core/util')
-const { InvalidArgumentError } = require('../core/errors')
-
-const kResume = Symbol('resume')
-
-class UnwrapController {
- #paused = false
- #reason = null
- #aborted = false
- #abort
-
- [kResume] = null
-
- constructor (abort) {
- this.#abort = abort
- }
-
- pause () {
- this.#paused = true
- }
-
- resume () {
- if (this.#paused) {
- this.#paused = false
- this[kResume]?.()
- }
- }
-
- abort (reason) {
- if (!this.#aborted) {
- this.#aborted = true
- this.#reason = reason
- this.#abort(reason)
- }
- }
-
- get aborted () {
- return this.#aborted
- }
-
- get reason () {
- return this.#reason
- }
-
- get paused () {
- return this.#paused
- }
-}
-
-module.exports = class UnwrapHandler {
- #handler
- #controller
-
- constructor (handler) {
- this.#handler = handler
- }
-
- static unwrap (handler) {
- // TODO (fix): More checks...
- return !handler.onRequestStart ? handler : new UnwrapHandler(handler)
- }
-
- onConnect (abort, context) {
- this.#controller = new UnwrapController(abort)
- this.#handler.onRequestStart?.(this.#controller, context)
- }
-
- onUpgrade (statusCode, rawHeaders, socket) {
- this.#handler.onRequestUpgrade?.(this.#controller, statusCode, parseHeaders(rawHeaders), socket)
- }
-
- onHeaders (statusCode, rawHeaders, resume, statusMessage) {
- this.#controller[kResume] = resume
- this.#handler.onResponseStart?.(this.#controller, statusCode, parseHeaders(rawHeaders), statusMessage)
- return !this.#controller.paused
- }
-
- onData (data) {
- this.#handler.onResponseData?.(this.#controller, data)
- return !this.#controller.paused
- }
-
- onComplete (rawTrailers) {
- this.#handler.onResponseEnd?.(this.#controller, parseHeaders(rawTrailers))
- }
-
- onError (err) {
- if (!this.#handler.onResponseError) {
- throw new InvalidArgumentError('invalid onError method')
- }
-
- this.#handler.onResponseError?.(this.#controller, err)
- }
-}
diff --git a/vanilla/node_modules/undici/lib/handler/wrap-handler.js b/vanilla/node_modules/undici/lib/handler/wrap-handler.js
deleted file mode 100644
index 47caa5f..0000000
--- a/vanilla/node_modules/undici/lib/handler/wrap-handler.js
+++ /dev/null
@@ -1,95 +0,0 @@
-'use strict'
-
-const { InvalidArgumentError } = require('../core/errors')
-
-module.exports = class WrapHandler {
- #handler
-
- constructor (handler) {
- this.#handler = handler
- }
-
- static wrap (handler) {
- // TODO (fix): More checks...
- return handler.onRequestStart ? handler : new WrapHandler(handler)
- }
-
- // Unwrap Interface
-
- onConnect (abort, context) {
- return this.#handler.onConnect?.(abort, context)
- }
-
- onHeaders (statusCode, rawHeaders, resume, statusMessage) {
- return this.#handler.onHeaders?.(statusCode, rawHeaders, resume, statusMessage)
- }
-
- onUpgrade (statusCode, rawHeaders, socket) {
- return this.#handler.onUpgrade?.(statusCode, rawHeaders, socket)
- }
-
- onData (data) {
- return this.#handler.onData?.(data)
- }
-
- onComplete (trailers) {
- return this.#handler.onComplete?.(trailers)
- }
-
- onError (err) {
- if (!this.#handler.onError) {
- throw err
- }
-
- return this.#handler.onError?.(err)
- }
-
- // Wrap Interface
-
- onRequestStart (controller, context) {
- this.#handler.onConnect?.((reason) => controller.abort(reason), context)
- }
-
- onRequestUpgrade (controller, statusCode, headers, socket) {
- const rawHeaders = []
- for (const [key, val] of Object.entries(headers)) {
- rawHeaders.push(Buffer.from(key), Array.isArray(val) ? val.map(v => Buffer.from(v)) : Buffer.from(val))
- }
-
- this.#handler.onUpgrade?.(statusCode, rawHeaders, socket)
- }
-
- onResponseStart (controller, statusCode, headers, statusMessage) {
- const rawHeaders = []
- for (const [key, val] of Object.entries(headers)) {
- rawHeaders.push(Buffer.from(key), Array.isArray(val) ? val.map(v => Buffer.from(v)) : Buffer.from(val))
- }
-
- if (this.#handler.onHeaders?.(statusCode, rawHeaders, () => controller.resume(), statusMessage) === false) {
- controller.pause()
- }
- }
-
- onResponseData (controller, data) {
- if (this.#handler.onData?.(data) === false) {
- controller.pause()
- }
- }
-
- onResponseEnd (controller, trailers) {
- const rawTrailers = []
- for (const [key, val] of Object.entries(trailers)) {
- rawTrailers.push(Buffer.from(key), Array.isArray(val) ? val.map(v => Buffer.from(v)) : Buffer.from(val))
- }
-
- this.#handler.onComplete?.(rawTrailers)
- }
-
- onResponseError (controller, err) {
- if (!this.#handler.onError) {
- throw new InvalidArgumentError('invalid onError method')
- }
-
- this.#handler.onError?.(err)
- }
-}