aboutsummaryrefslogtreecommitdiffstats
path: root/node_modules/undici/lib/handler
diff options
context:
space:
mode:
authorpack <pack@packgekko.xyz>2026-08-09 10:54:08 +0000
committerpack <pack@packgekko.xyz>2026-08-09 10:54:08 +0000
commitd3adc16a08d95d6e331de55d7d3bf05a66a874a8 (patch)
treea2dabd199501e67c547c2ce79e1374ca3aa55443 /node_modules/undici/lib/handler
parent55a4f1fc869e41aca748c63d3018f0448b1606e0 (diff)
downloadcrud-d3adc16a08d95d6e331de55d7d3bf05a66a874a8.tar.gz
stop tracking node_modules/
Diffstat (limited to '')
-rw-r--r--node_modules/undici/lib/handler/decorator-handler.js44
-rw-r--r--node_modules/undici/lib/handler/redirect-handler.js232
-rw-r--r--node_modules/undici/lib/handler/retry-handler.js408
3 files changed, 0 insertions, 684 deletions
diff --git a/node_modules/undici/lib/handler/decorator-handler.js b/node_modules/undici/lib/handler/decorator-handler.js
deleted file mode 100644
index 26f220c..0000000
--- a/node_modules/undici/lib/handler/decorator-handler.js
+++ /dev/null
@@ -1,44 +0,0 @@
-'use strict'
-
-module.exports = class DecoratorHandler {
- #handler
-
- constructor (handler) {
- if (typeof handler !== 'object' || handler === null) {
- throw new TypeError('handler must be an object')
- }
- this.#handler = handler
- }
-
- onConnect (...args) {
- return this.#handler.onConnect?.(...args)
- }
-
- onError (...args) {
- return this.#handler.onError?.(...args)
- }
-
- onUpgrade (...args) {
- return this.#handler.onUpgrade?.(...args)
- }
-
- onResponseStarted (...args) {
- return this.#handler.onResponseStarted?.(...args)
- }
-
- onHeaders (...args) {
- return this.#handler.onHeaders?.(...args)
- }
-
- onData (...args) {
- return this.#handler.onData?.(...args)
- }
-
- onComplete (...args) {
- return this.#handler.onComplete?.(...args)
- }
-
- onBodySent (...args) {
- return this.#handler.onBodySent?.(...args)
- }
-}
diff --git a/node_modules/undici/lib/handler/redirect-handler.js b/node_modules/undici/lib/handler/redirect-handler.js
deleted file mode 100644
index 16a7b21..0000000
--- a/node_modules/undici/lib/handler/redirect-handler.js
+++ /dev/null
@@ -1,232 +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')
-
-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 {
- constructor (dispatch, maxRedirections, opts, handler) {
- if (maxRedirections != null && (!Number.isInteger(maxRedirections) || maxRedirections < 0)) {
- throw new InvalidArgumentError('maxRedirections must be a positive number')
- }
-
- util.validateHandler(handler, opts.method, opts.upgrade)
-
- this.dispatch = dispatch
- this.location = null
- this.abort = null
- this.opts = { ...opts, maxRedirections: 0 } // opts must be a copy
- this.maxRedirections = maxRedirections
- this.handler = handler
- this.history = []
- this.redirectionLimitReached = false
-
- 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)
- ) {
- // TODO: Should we allow re-using iterable if !this.opts.idempotent
- // or through some other flag?
- this.opts.body = new BodyAsyncIterable(this.opts.body)
- }
- }
-
- onConnect (abort) {
- this.abort = abort
- this.handler.onConnect(abort, { history: this.history })
- }
-
- onUpgrade (statusCode, headers, socket) {
- this.handler.onUpgrade(statusCode, headers, socket)
- }
-
- onError (error) {
- this.handler.onError(error)
- }
-
- onHeaders (statusCode, headers, resume, statusText) {
- this.location = this.history.length >= this.maxRedirections || util.isDisturbed(this.opts.body)
- ? null
- : parseLocation(statusCode, headers)
-
- if (this.opts.throwOnMaxRedirect && this.history.length >= this.maxRedirections) {
- if (this.request) {
- this.request.abort(new Error('max redirects'))
- }
-
- this.redirectionLimitReached = true
- this.abort(new Error('max redirects'))
- return
- }
-
- if (this.opts.origin) {
- this.history.push(new URL(this.opts.path, this.opts.origin))
- }
-
- if (!this.location) {
- return this.handler.onHeaders(statusCode, headers, resume, statusText)
- }
-
- 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
-
- // 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.maxRedirections = 0
- this.opts.query = 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'
- this.opts.body = null
- }
- }
-
- onData (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 is 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 {
- return this.handler.onData(chunk)
- }
- }
-
- onComplete (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.location = null
- this.abort = null
-
- this.dispatch(this.opts, this)
- } else {
- this.handler.onComplete(trailers)
- }
- }
-
- onBodySent (chunk) {
- if (this.handler.onBodySent) {
- this.handler.onBodySent(chunk)
- }
- }
-}
-
-function parseLocation (statusCode, headers) {
- if (redirectableStatusCodes.indexOf(statusCode) === -1) {
- return null
- }
-
- for (let i = 0; i < headers.length; i += 2) {
- if (headers[i].length === 8 && util.headerNameToString(headers[i]) === 'location') {
- return headers[i + 1]
- }
- }
-}
-
-// 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') {
- for (const key of Object.keys(headers)) {
- if (!shouldRemoveHeader(key, removeContent, unknownOrigin)) {
- ret.push(key, headers[key])
- }
- }
- } else {
- assert(headers == null, 'headers must be an object or an array')
- }
- return ret
-}
-
-module.exports = RedirectHandler
diff --git a/node_modules/undici/lib/handler/retry-handler.js b/node_modules/undici/lib/handler/retry-handler.js
deleted file mode 100644
index c62a240..0000000
--- a/node_modules/undici/lib/handler/retry-handler.js
+++ /dev/null
@@ -1,408 +0,0 @@
-'use strict'
-const assert = require('node:assert')
-
-const { kRetryHandlerDefaultRetry } = require('../core/symbols')
-const { RequestRetryError } = require('../core/errors')
-const {
- isDisturbed,
- parseHeaders,
- parseRangeHeader,
- wrapRequestBody
-} = require('../core/util')
-
-function calculateRetryAfterHeader (retryAfter) {
- const current = Date.now()
- return new Date(retryAfter).getTime() - current
-}
-
-function validatePartialResponseContentLength (headers, range, statusCode, retryCount) {
- const contentLength = headers['content-length']
- if (contentLength == null) {
- return null
- }
-
- if (!Number.isFinite(range.start) || !Number.isFinite(range.end)) {
- return null
- }
-
- const length = Number(contentLength)
- const expectedLength = range.end - range.start + 1
- if (!Number.isFinite(length) || length !== expectedLength) {
- return new RequestRetryError('Content-Length mismatch', statusCode, {
- headers,
- data: { count: retryCount }
- })
- }
-
- return null
-}
-
-class RetryHandler {
- constructor (opts, handlers) {
- const { retryOptions, ...dispatchOpts } = opts
- const {
- // Retry scoped
- retry: retryFn,
- maxRetries,
- maxTimeout,
- minTimeout,
- timeoutFactor,
- // Response scoped
- methods,
- errorCodes,
- retryAfter,
- statusCodes
- } = retryOptions ?? {}
-
- this.dispatch = handlers.dispatch
- this.handler = handlers.handler
- this.opts = { ...dispatchOpts, body: wrapRequestBody(opts.body) }
- this.abort = null
- this.aborted = false
- this.retryOpts = {
- 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.start = 0
- this.end = null
- this.etag = null
- this.resume = null
-
- // Handle possible onConnect duplication
- this.handler.onConnect(reason => {
- this.aborted = true
- if (this.abort) {
- this.abort(reason)
- } else {
- this.reason = reason
- }
- })
- }
-
- onRequestSent () {
- if (this.handler.onRequestSent) {
- this.handler.onRequestSent()
- }
- }
-
- onUpgrade (statusCode, headers, socket) {
- if (this.handler.onUpgrade) {
- this.handler.onUpgrade(statusCode, headers, socket)
- }
- }
-
- onConnect (abort) {
- if (this.aborted) {
- abort(this.reason)
- } else {
- this.abort = abort
- }
- }
-
- onBodySent (chunk) {
- if (this.handler.onBodySent) return this.handler.onBodySent(chunk)
- }
-
- 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(retryAfterHeader)
- : 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)
- }
-
- onHeaders (statusCode, rawHeaders, resume, statusMessage) {
- const headers = parseHeaders(rawHeaders)
-
- this.retryCount += 1
-
- if (statusCode >= 300) {
- if (this.retryOpts.statusCodes.includes(statusCode) === false) {
- return this.handler.onHeaders(
- statusCode,
- rawHeaders,
- resume,
- statusMessage
- )
- } else {
- this.abort(
- new RequestRetryError('Request failed', statusCode, {
- headers,
- data: {
- count: this.retryCount
- }
- })
- )
- return false
- }
- }
-
- // Checkpoint for resume from where we left it
- if (this.resume != null) {
- this.resume = null
-
- // Only Partial Content 206 supposed to provide Content-Range,
- // any other status code that partially consumed the payload
- // should not be retry because it would result in downstream
- // wrongly concatanete multiple responses.
- if (statusCode !== 206 && (this.start > 0 || statusCode !== 200)) {
- this.abort(
- new RequestRetryError('server does not support the range header and the payload was partially consumed', statusCode, {
- headers,
- data: { count: this.retryCount }
- })
- )
- return false
- }
-
- const contentRange = parseRangeHeader(headers['content-range'])
- // If no content range
- if (!contentRange) {
- this.abort(
- new RequestRetryError('Content-Range mismatch', statusCode, {
- headers,
- data: { count: this.retryCount }
- })
- )
- return false
- }
-
- // Let's start with a weak etag check
- if (this.etag != null && this.etag !== headers.etag) {
- this.abort(
- new RequestRetryError('ETag mismatch', statusCode, {
- headers,
- data: { count: this.retryCount }
- })
- )
- return false
- }
-
- const contentLengthError = validatePartialResponseContentLength(headers, contentRange, statusCode, this.retryCount)
- if (contentLengthError != null) {
- this.abort(contentLengthError)
- return false
- }
-
- const { start, size, end = size - 1 } = contentRange
-
- assert(this.start === start, 'content-range mismatch')
- assert(this.end == null || this.end === end, 'content-range mismatch')
-
- this.resume = resume
- return true
- }
-
- if (this.end == null) {
- if (statusCode === 206) {
- // First time we receive 206
- const range = parseRangeHeader(headers['content-range'])
-
- if (range == null) {
- return this.handler.onHeaders(
- statusCode,
- rawHeaders,
- resume,
- statusMessage
- )
- }
-
- const contentLengthError = validatePartialResponseContentLength(headers, range, statusCode, this.retryCount)
- if (contentLengthError != null) {
- this.abort(contentLengthError)
- return false
- }
-
- const { start, size, end = size - 1 } = 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 = resume
- 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.startsWith('W/')) {
- this.etag = null
- }
-
- return this.handler.onHeaders(
- statusCode,
- rawHeaders,
- resume,
- statusMessage
- )
- }
-
- const err = new RequestRetryError('Request failed', statusCode, {
- headers,
- data: { count: this.retryCount }
- })
-
- this.abort(err)
-
- return false
- }
-
- onData (chunk) {
- this.start += chunk.length
-
- return this.handler.onData(chunk)
- }
-
- onComplete (rawTrailers) {
- this.retryCount = 0
- return this.handler.onComplete(rawTrailers)
- }
-
- onError (err) {
- if (this.aborted || isDisturbed(this.opts.body)) {
- return this.handler.onError(err)
- }
-
- // 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 }
- },
- onRetry.bind(this)
- )
-
- function onRetry (err) {
- if (err != null || this.aborted || isDisturbed(this.opts.body)) {
- return this.handler.onError(err)
- }
-
- 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.onError(err)
- }
- }
- }
-}
-
-module.exports = RetryHandler