aboutsummaryrefslogtreecommitdiffstats
path: root/node_modules/undici/lib/interceptor
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/undici/lib/interceptor')
-rw-r--r--node_modules/undici/lib/interceptor/dns.js375
-rw-r--r--node_modules/undici/lib/interceptor/dump.js123
-rw-r--r--node_modules/undici/lib/interceptor/redirect-interceptor.js21
-rw-r--r--node_modules/undici/lib/interceptor/redirect.js24
-rw-r--r--node_modules/undici/lib/interceptor/response-error.js86
-rw-r--r--node_modules/undici/lib/interceptor/retry.js19
6 files changed, 0 insertions, 648 deletions
diff --git a/node_modules/undici/lib/interceptor/dns.js b/node_modules/undici/lib/interceptor/dns.js
deleted file mode 100644
index 9177326..0000000
--- a/node_modules/undici/lib/interceptor/dns.js
+++ /dev/null
@@ -1,375 +0,0 @@
-'use strict'
-const { isIP } = require('node:net')
-const { lookup } = require('node:dns')
-const DecoratorHandler = require('../handler/decorator-handler')
-const { InvalidArgumentError, InformationalError } = require('../core/errors')
-const maxInt = Math.pow(2, 31) - 1
-
-class DNSInstance {
- #maxTTL = 0
- #maxItems = 0
- #records = new Map()
- dualStack = true
- affinity = null
- lookup = null
- pick = null
-
- constructor (opts) {
- this.#maxTTL = opts.maxTTL
- this.#maxItems = opts.maxItems
- this.dualStack = opts.dualStack
- this.affinity = opts.affinity
- this.lookup = opts.lookup ?? this.#defaultLookup
- this.pick = opts.pick ?? this.#defaultPick
- }
-
- get full () {
- return this.#records.size === this.#maxItems
- }
-
- runLookup (origin, opts, cb) {
- const ips = this.#records.get(origin.hostname)
-
- // If full, we just return the origin
- if (ips == null && this.full) {
- cb(null, origin.origin)
- return
- }
-
- const newOpts = {
- affinity: this.affinity,
- dualStack: this.dualStack,
- lookup: this.lookup,
- pick: this.pick,
- ...opts.dns,
- maxTTL: this.#maxTTL,
- maxItems: this.#maxItems
- }
-
- // If no IPs we lookup
- if (ips == null) {
- this.lookup(origin, newOpts, (err, addresses) => {
- if (err || addresses == null || addresses.length === 0) {
- cb(err ?? new InformationalError('No DNS entries found'))
- return
- }
-
- this.setRecords(origin, addresses)
- const records = this.#records.get(origin.hostname)
-
- const ip = this.pick(
- origin,
- records,
- newOpts.affinity
- )
-
- let port
- if (typeof ip.port === 'number') {
- port = `:${ip.port}`
- } else if (origin.port !== '') {
- port = `:${origin.port}`
- } else {
- port = ''
- }
-
- cb(
- null,
- `${origin.protocol}//${
- ip.family === 6 ? `[${ip.address}]` : ip.address
- }${port}`
- )
- })
- } else {
- // If there's IPs we pick
- const ip = this.pick(
- origin,
- ips,
- newOpts.affinity
- )
-
- // If no IPs we lookup - deleting old records
- if (ip == null) {
- this.#records.delete(origin.hostname)
- this.runLookup(origin, opts, cb)
- return
- }
-
- let port
- if (typeof ip.port === 'number') {
- port = `:${ip.port}`
- } else if (origin.port !== '') {
- port = `:${origin.port}`
- } else {
- port = ''
- }
-
- cb(
- null,
- `${origin.protocol}//${
- ip.family === 6 ? `[${ip.address}]` : ip.address
- }${port}`
- )
- }
- }
-
- #defaultLookup (origin, opts, cb) {
- lookup(
- origin.hostname,
- {
- all: true,
- family: this.dualStack === false ? this.affinity : 0,
- order: 'ipv4first'
- },
- (err, addresses) => {
- if (err) {
- return cb(err)
- }
-
- const results = new Map()
-
- for (const addr of addresses) {
- // On linux we found duplicates, we attempt to remove them with
- // the latest record
- results.set(`${addr.address}:${addr.family}`, addr)
- }
-
- cb(null, results.values())
- }
- )
- }
-
- #defaultPick (origin, hostnameRecords, affinity) {
- let ip = null
- const { records, offset } = hostnameRecords
-
- let family
- if (this.dualStack) {
- if (affinity == null) {
- // Balance between ip families
- if (offset == null || offset === maxInt) {
- hostnameRecords.offset = 0
- affinity = 4
- } else {
- hostnameRecords.offset++
- affinity = (hostnameRecords.offset & 1) === 1 ? 6 : 4
- }
- }
-
- if (records[affinity] != null && records[affinity].ips.length > 0) {
- family = records[affinity]
- } else {
- family = records[affinity === 4 ? 6 : 4]
- }
- } else {
- family = records[affinity]
- }
-
- // If no IPs we return null
- if (family == null || family.ips.length === 0) {
- return ip
- }
-
- if (family.offset == null || family.offset === maxInt) {
- family.offset = 0
- } else {
- family.offset++
- }
-
- const position = family.offset % family.ips.length
- ip = family.ips[position] ?? null
-
- if (ip == null) {
- return ip
- }
-
- if (Date.now() - ip.timestamp > ip.ttl) { // record TTL is already in ms
- // We delete expired records
- // It is possible that they have different TTL, so we manage them individually
- family.ips.splice(position, 1)
- return this.pick(origin, hostnameRecords, affinity)
- }
-
- return ip
- }
-
- setRecords (origin, addresses) {
- const timestamp = Date.now()
- const records = { records: { 4: null, 6: null } }
- for (const record of addresses) {
- record.timestamp = timestamp
- if (typeof record.ttl === 'number') {
- // The record TTL is expected to be in ms
- record.ttl = Math.min(record.ttl, this.#maxTTL)
- } else {
- record.ttl = this.#maxTTL
- }
-
- const familyRecords = records.records[record.family] ?? { ips: [] }
-
- familyRecords.ips.push(record)
- records.records[record.family] = familyRecords
- }
-
- this.#records.set(origin.hostname, records)
- }
-
- getHandler (meta, opts) {
- return new DNSDispatchHandler(this, meta, opts)
- }
-}
-
-class DNSDispatchHandler extends DecoratorHandler {
- #state = null
- #opts = null
- #dispatch = null
- #handler = null
- #origin = null
-
- constructor (state, { origin, handler, dispatch }, opts) {
- super(handler)
- this.#origin = origin
- this.#handler = handler
- this.#opts = { ...opts }
- this.#state = state
- this.#dispatch = dispatch
- }
-
- onError (err) {
- switch (err.code) {
- case 'ETIMEDOUT':
- case 'ECONNREFUSED': {
- if (this.#state.dualStack) {
- // We delete the record and retry
- this.#state.runLookup(this.#origin, this.#opts, (err, newOrigin) => {
- if (err) {
- return this.#handler.onError(err)
- }
-
- const dispatchOpts = {
- ...this.#opts,
- origin: newOrigin
- }
-
- this.#dispatch(dispatchOpts, this)
- })
-
- // if dual-stack disabled, we error out
- return
- }
-
- this.#handler.onError(err)
- return
- }
- case 'ENOTFOUND':
- this.#state.deleteRecord(this.#origin)
- // eslint-disable-next-line no-fallthrough
- default:
- this.#handler.onError(err)
- break
- }
- }
-}
-
-module.exports = interceptorOpts => {
- if (
- interceptorOpts?.maxTTL != null &&
- (typeof interceptorOpts?.maxTTL !== 'number' || interceptorOpts?.maxTTL < 0)
- ) {
- throw new InvalidArgumentError('Invalid maxTTL. Must be a positive number')
- }
-
- if (
- interceptorOpts?.maxItems != null &&
- (typeof interceptorOpts?.maxItems !== 'number' ||
- interceptorOpts?.maxItems < 1)
- ) {
- throw new InvalidArgumentError(
- 'Invalid maxItems. Must be a positive number and greater than zero'
- )
- }
-
- if (
- interceptorOpts?.affinity != null &&
- interceptorOpts?.affinity !== 4 &&
- interceptorOpts?.affinity !== 6
- ) {
- throw new InvalidArgumentError('Invalid affinity. Must be either 4 or 6')
- }
-
- if (
- interceptorOpts?.dualStack != null &&
- typeof interceptorOpts?.dualStack !== 'boolean'
- ) {
- throw new InvalidArgumentError('Invalid dualStack. Must be a boolean')
- }
-
- if (
- interceptorOpts?.lookup != null &&
- typeof interceptorOpts?.lookup !== 'function'
- ) {
- throw new InvalidArgumentError('Invalid lookup. Must be a function')
- }
-
- if (
- interceptorOpts?.pick != null &&
- typeof interceptorOpts?.pick !== 'function'
- ) {
- throw new InvalidArgumentError('Invalid pick. Must be a function')
- }
-
- const dualStack = interceptorOpts?.dualStack ?? true
- let affinity
- if (dualStack) {
- affinity = interceptorOpts?.affinity ?? null
- } else {
- affinity = interceptorOpts?.affinity ?? 4
- }
-
- const opts = {
- maxTTL: interceptorOpts?.maxTTL ?? 10e3, // Expressed in ms
- lookup: interceptorOpts?.lookup ?? null,
- pick: interceptorOpts?.pick ?? null,
- dualStack,
- affinity,
- maxItems: interceptorOpts?.maxItems ?? Infinity
- }
-
- const instance = new DNSInstance(opts)
-
- return dispatch => {
- return function dnsInterceptor (origDispatchOpts, handler) {
- const origin =
- origDispatchOpts.origin.constructor === URL
- ? origDispatchOpts.origin
- : new URL(origDispatchOpts.origin)
-
- if (isIP(origin.hostname) !== 0) {
- return dispatch(origDispatchOpts, handler)
- }
-
- instance.runLookup(origin, origDispatchOpts, (err, newOrigin) => {
- if (err) {
- return handler.onError(err)
- }
-
- let dispatchOpts = null
- dispatchOpts = {
- ...origDispatchOpts,
- servername: origin.hostname, // For SNI on TLS
- origin: newOrigin,
- headers: {
- host: origin.hostname,
- ...origDispatchOpts.headers
- }
- }
-
- dispatch(
- dispatchOpts,
- instance.getHandler({ origin, dispatch, handler }, origDispatchOpts)
- )
- })
-
- return true
- }
- }
-}
diff --git a/node_modules/undici/lib/interceptor/dump.js b/node_modules/undici/lib/interceptor/dump.js
deleted file mode 100644
index fc9cacb..0000000
--- a/node_modules/undici/lib/interceptor/dump.js
+++ /dev/null
@@ -1,123 +0,0 @@
-'use strict'
-
-const util = require('../core/util')
-const { InvalidArgumentError, RequestAbortedError } = require('../core/errors')
-const DecoratorHandler = require('../handler/decorator-handler')
-
-class DumpHandler extends DecoratorHandler {
- #maxSize = 1024 * 1024
- #abort = null
- #dumped = false
- #aborted = false
- #size = 0
- #reason = null
- #handler = null
-
- constructor ({ maxSize }, handler) {
- super(handler)
-
- if (maxSize != null && (!Number.isFinite(maxSize) || maxSize < 1)) {
- throw new InvalidArgumentError('maxSize must be a number greater than 0')
- }
-
- this.#maxSize = maxSize ?? this.#maxSize
- this.#handler = handler
- }
-
- onConnect (abort) {
- this.#abort = abort
-
- this.#handler.onConnect(this.#customAbort.bind(this))
- }
-
- #customAbort (reason) {
- this.#aborted = true
- this.#reason = reason
- }
-
- // TODO: will require adjustment after new hooks are out
- onHeaders (statusCode, rawHeaders, resume, statusMessage) {
- const headers = util.parseHeaders(rawHeaders)
- const contentLength = headers['content-length']
-
- if (contentLength != null && contentLength > this.#maxSize) {
- throw new RequestAbortedError(
- `Response size (${contentLength}) larger than maxSize (${
- this.#maxSize
- })`
- )
- }
-
- if (this.#aborted) {
- return true
- }
-
- return this.#handler.onHeaders(
- statusCode,
- rawHeaders,
- resume,
- statusMessage
- )
- }
-
- onError (err) {
- if (this.#dumped) {
- return
- }
-
- err = this.#reason ?? err
-
- this.#handler.onError(err)
- }
-
- onData (chunk) {
- this.#size = this.#size + chunk.length
-
- if (this.#size >= this.#maxSize) {
- this.#dumped = true
-
- if (this.#aborted) {
- this.#handler.onError(this.#reason)
- } else {
- this.#handler.onComplete([])
- }
- }
-
- return true
- }
-
- onComplete (trailers) {
- if (this.#dumped) {
- return
- }
-
- if (this.#aborted) {
- this.#handler.onError(this.reason)
- return
- }
-
- this.#handler.onComplete(trailers)
- }
-}
-
-function createDumpInterceptor (
- { maxSize: defaultMaxSize } = {
- maxSize: 1024 * 1024
- }
-) {
- return dispatch => {
- return function Intercept (opts, handler) {
- const { dumpMaxSize = defaultMaxSize } =
- opts
-
- const dumpHandler = new DumpHandler(
- { maxSize: dumpMaxSize },
- handler
- )
-
- return dispatch(opts, dumpHandler)
- }
- }
-}
-
-module.exports = createDumpInterceptor
diff --git a/node_modules/undici/lib/interceptor/redirect-interceptor.js b/node_modules/undici/lib/interceptor/redirect-interceptor.js
deleted file mode 100644
index 896ee8d..0000000
--- a/node_modules/undici/lib/interceptor/redirect-interceptor.js
+++ /dev/null
@@ -1,21 +0,0 @@
-'use strict'
-
-const RedirectHandler = require('../handler/redirect-handler')
-
-function createRedirectInterceptor ({ maxRedirections: defaultMaxRedirections }) {
- return (dispatch) => {
- return function Intercept (opts, handler) {
- const { maxRedirections = defaultMaxRedirections } = opts
-
- if (!maxRedirections) {
- return dispatch(opts, handler)
- }
-
- const redirectHandler = new RedirectHandler(dispatch, maxRedirections, opts, handler)
- opts = { ...opts, maxRedirections: 0 } // Stop sub dispatcher from also redirecting.
- return dispatch(opts, redirectHandler)
- }
- }
-}
-
-module.exports = createRedirectInterceptor
diff --git a/node_modules/undici/lib/interceptor/redirect.js b/node_modules/undici/lib/interceptor/redirect.js
deleted file mode 100644
index d2e789d..0000000
--- a/node_modules/undici/lib/interceptor/redirect.js
+++ /dev/null
@@ -1,24 +0,0 @@
-'use strict'
-const RedirectHandler = require('../handler/redirect-handler')
-
-module.exports = opts => {
- const globalMaxRedirections = opts?.maxRedirections
- return dispatch => {
- return function redirectInterceptor (opts, handler) {
- const { maxRedirections = globalMaxRedirections, ...baseOpts } = opts
-
- if (!maxRedirections) {
- return dispatch(opts, handler)
- }
-
- const redirectHandler = new RedirectHandler(
- dispatch,
- maxRedirections,
- opts,
- handler
- )
-
- return dispatch(baseOpts, redirectHandler)
- }
- }
-}
diff --git a/node_modules/undici/lib/interceptor/response-error.js b/node_modules/undici/lib/interceptor/response-error.js
deleted file mode 100644
index 3ded9c8..0000000
--- a/node_modules/undici/lib/interceptor/response-error.js
+++ /dev/null
@@ -1,86 +0,0 @@
-'use strict'
-
-const { parseHeaders } = require('../core/util')
-const DecoratorHandler = require('../handler/decorator-handler')
-const { ResponseError } = require('../core/errors')
-
-class Handler extends DecoratorHandler {
- #handler
- #statusCode
- #contentType
- #decoder
- #headers
- #body
-
- constructor (opts, { handler }) {
- super(handler)
- this.#handler = handler
- }
-
- onConnect (abort) {
- this.#statusCode = 0
- this.#contentType = null
- this.#decoder = null
- this.#headers = null
- this.#body = ''
-
- return this.#handler.onConnect(abort)
- }
-
- onHeaders (statusCode, rawHeaders, resume, statusMessage, headers = parseHeaders(rawHeaders)) {
- this.#statusCode = statusCode
- this.#headers = headers
- this.#contentType = headers['content-type']
-
- if (this.#statusCode < 400) {
- return this.#handler.onHeaders(statusCode, rawHeaders, resume, statusMessage, headers)
- }
-
- if (this.#contentType === 'application/json' || this.#contentType === 'text/plain') {
- this.#decoder = new TextDecoder('utf-8')
- }
- }
-
- onData (chunk) {
- if (this.#statusCode < 400) {
- return this.#handler.onData(chunk)
- }
-
- this.#body += this.#decoder?.decode(chunk, { stream: true }) ?? ''
- }
-
- onComplete (rawTrailers) {
- if (this.#statusCode >= 400) {
- this.#body += this.#decoder?.decode(undefined, { stream: false }) ?? ''
-
- if (this.#contentType === 'application/json') {
- try {
- this.#body = JSON.parse(this.#body)
- } catch {
- // Do nothing...
- }
- }
-
- let err
- const stackTraceLimit = Error.stackTraceLimit
- Error.stackTraceLimit = 0
- try {
- err = new ResponseError('Response Error', this.#statusCode, this.#headers, this.#body)
- } finally {
- Error.stackTraceLimit = stackTraceLimit
- }
-
- this.#handler.onError(err)
- } else {
- this.#handler.onComplete(rawTrailers)
- }
- }
-
- onError (err) {
- this.#handler.onError(err)
- }
-}
-
-module.exports = (dispatch) => (opts, handler) => opts.throwOnError
- ? dispatch(opts, new Handler(opts, { handler }))
- : dispatch(opts, handler)
diff --git a/node_modules/undici/lib/interceptor/retry.js b/node_modules/undici/lib/interceptor/retry.js
deleted file mode 100644
index 1c16fd8..0000000
--- a/node_modules/undici/lib/interceptor/retry.js
+++ /dev/null
@@ -1,19 +0,0 @@
-'use strict'
-const RetryHandler = require('../handler/retry-handler')
-
-module.exports = globalOpts => {
- return dispatch => {
- return function retryInterceptor (opts, handler) {
- return dispatch(
- opts,
- new RetryHandler(
- { ...opts, retryOptions: { ...globalOpts, ...opts.retryOptions } },
- {
- handler,
- dispatch
- }
- )
- )
- }
- }
-}