From f2704b132f328246bc052e4aa39b086351add0e0 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah <36107+shazron@users.noreply.github.com> Date: Thu, 13 Nov 2025 13:38:11 +0800 Subject: [PATCH 1/3] fix: ACNA-4162 - add constructor options to set log level --- README.md | 37 +++++++++++++++++------ src/HttpExponentialBackoff.js | 27 ++++++++++++----- src/ProxyFetch.js | 43 ++++++++++++++------------ src/utils.js | 18 +++++------ test/HttpExponentialBackoff.test.js | 47 +++++++++++++++++++++++++++++ types.d.ts | 23 ++++++++------ 6 files changed, 140 insertions(+), 55 deletions(-) diff --git a/README.md b/README.md index a8876c0..fa3856c 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ with defaults set to max of 3 retries and initial Delay as 100ms

## Functions
-
createFetch([proxyAuthOptions])function
+
createFetch([proxyOptions])function

Return the appropriate Fetch function depending on proxy settings.

parseRetryAfterHeader(header)number
@@ -106,7 +106,7 @@ Spec: https://tools.
RetryOptions : object

Fetch Retry Options

-
ProxyAuthOptions : object
+
ProxyOptions : object

Proxy Auth Options

@@ -119,6 +119,22 @@ The retries use exponential backoff strategy with defaults set to max of 3 retries and initial Delay as 100ms **Kind**: global class + +* [HttpExponentialBackoff](#HttpExponentialBackoff) + * [new HttpExponentialBackoff([options])](#new_HttpExponentialBackoff_new) + * [.exponentialBackoff(url, requestOptions, [retryOptions], [retryOn], [retryDelay])](#HttpExponentialBackoff+exponentialBackoff) ⇒ Promise.<Response> + + + +### new HttpExponentialBackoff([options]) +Creates an instance of HttpExponentialBackoff + + +| Param | Type | Description | +| --- | --- | --- | +| [options] | object | configuration options | +| [options.logLevel] | string | the log level to use (default: process.env.LOG_LEVEL or 'info') | + ### httpExponentialBackoff.exponentialBackoff(url, requestOptions, [retryOptions], [retryOn], [retryDelay]) ⇒ Promise.<Response> @@ -144,18 +160,18 @@ This provides a wrapper for fetch that facilitates proxy auth authorization. **Kind**: global class * [ProxyFetch](#ProxyFetch) - * [new ProxyFetch(proxyAuthOptions)](#new_ProxyFetch_new) + * [new ProxyFetch(proxyOptions)](#new_ProxyFetch_new) * [.fetch(resource, options)](#ProxyFetch+fetch) ⇒ Promise.<Response> -### new ProxyFetch(proxyAuthOptions) +### new ProxyFetch(proxyOptions) Initialize this class with Proxy auth options | Param | Type | Description | | --- | --- | --- | -| proxyAuthOptions | [ProxyAuthOptions](#ProxyAuthOptions) | the auth options to connect with | +| proxyOptions | [ProxyOptions](#ProxyOptions) | the auth options to connect with | @@ -172,7 +188,7 @@ Fetch function, using the configured NTLM Auth options. -## createFetch([proxyAuthOptions]) ⇒ function +## createFetch([proxyOptions]) ⇒ function Return the appropriate Fetch function depending on proxy settings. **Kind**: global function @@ -180,7 +196,7 @@ Return the appropriate Fetch function depending on proxy settings. | Param | Type | Description | | --- | --- | --- | -| [proxyAuthOptions] | [ProxyAuthOptions](#ProxyAuthOptions) | the proxy auth options | +| [proxyOptions] | [ProxyOptions](#ProxyOptions) | the proxy options | @@ -207,11 +223,11 @@ Fetch Retry Options | --- | --- | --- | | maxRetries | number | the maximum number of retries to try (default:3) | | initialDelayInMillis | number | the initial delay in milliseconds (default:100ms) | -| proxy | [ProxyAuthOptions](#ProxyAuthOptions) | the (optional) proxy auth options | +| proxy | [ProxyOptions](#ProxyOptions) | the (optional) proxy auth options | - + -## ProxyAuthOptions : object +## ProxyOptions : object Proxy Auth Options **Kind**: global typedef @@ -223,6 +239,7 @@ Proxy Auth Options | [username] | string | the username for basic auth | | [password] | string | the password for basic auth | | rejectUnauthorized | boolean | set to false to not reject unauthorized server certs | +| [logLevel] | string | the log level to use (default: process.env.LOG_LEVEL or 'info') | ### Debug Logs diff --git a/src/HttpExponentialBackoff.js b/src/HttpExponentialBackoff.js index ee5ab3c..b8dc4c0 100644 --- a/src/HttpExponentialBackoff.js +++ b/src/HttpExponentialBackoff.js @@ -12,10 +12,10 @@ governing permissions and limitations under the License. const DEFAULT_MAX_RETRIES = 3 const DEFAULT_INITIAL_DELAY_MS = 100 const loggerNamespace = '@adobe/aio-lib-core-networking:HttpExponentialBackoff' -const logger = require('@adobe/aio-lib-core-logging')(loggerNamespace, { level: process.env.LOG_LEVEL }) +const coreLogging = require('@adobe/aio-lib-core-logging') const { createFetch, parseRetryAfterHeader } = require('./utils') -/* global Request, Response, ProxyAuthOptions */ // for linter +/* global Request, Response, ProxyOptions */ // for linter /** * Fetch Retry Options @@ -23,7 +23,7 @@ const { createFetch, parseRetryAfterHeader } = require('./utils') * @typedef {object} RetryOptions * @property {number} maxRetries the maximum number of retries to try (default:3) * @property {number} initialDelayInMillis the initial delay in milliseconds (default:100ms) - * @property {ProxyAuthOptions} proxy the (optional) proxy auth options + * @property {ProxyOptions} proxy the (optional) proxy auth options */ /** @@ -32,6 +32,17 @@ const { createFetch, parseRetryAfterHeader } = require('./utils') * with defaults set to max of 3 retries and initial Delay as 100ms */ class HttpExponentialBackoff { + /** + * Creates an instance of HttpExponentialBackoff + * + * @param {object} [options] configuration options + * @param {string} [options.logLevel] the log level to use (default: process.env.LOG_LEVEL or 'info') + */ + constructor (options = {}) { + this.logLevel = options.logLevel || process.env.LOG_LEVEL || 'info' + this.logger = coreLogging(loggerNamespace, { level: this.logLevel }) + } + /** * This function will retry connecting to a url end-point, with * exponential backoff. Returns a Promise. @@ -102,10 +113,10 @@ class HttpExponentialBackoff { * @private */ __getRetryOn (retries) { - return function (attempt, error, response) { + return (attempt, error, response) => { if (attempt < retries && (error !== null || (response.status > 499 && response.status < 600) || response.status === 429)) { const msg = `Retrying after attempt ${attempt + 1}. failed: ${error || response.statusText}` - logger.debug(msg) + this.logger.debug(msg) return true } return false @@ -120,10 +131,10 @@ class HttpExponentialBackoff { * @private */ __getRetryDelay (initialDelayInMillis) { - return function (attempt, error, response) { + return (attempt, error, response) => { const timeToWait = Math.pow(2, attempt) * initialDelayInMillis // 1000, 2000, 4000 const msg = `Request will be retried after ${timeToWait} ms` - logger.debug(msg) + this.logger.debug(msg) return timeToWait } } @@ -142,7 +153,7 @@ class HttpExponentialBackoff { const retryAfter = response?.headers.get('Retry-After') || null const timeToWait = parseRetryAfterHeader(retryAfter) if (!isNaN(timeToWait)) { - logger.debug(`Request will be retried after ${timeToWait} ms`) + this.logger.debug(`Request will be retried after ${timeToWait} ms`) return timeToWait } return this.__getRetryDelay(initialDelayInMillis)(attempt, error, response) diff --git a/src/ProxyFetch.js b/src/ProxyFetch.js index c94378a..76cc41f 100644 --- a/src/ProxyFetch.js +++ b/src/ProxyFetch.js @@ -10,7 +10,7 @@ governing permissions and limitations under the License. */ const loggerNamespace = '@adobe/aio-lib-core-networking:ProxyFetch' -const logger = require('@adobe/aio-lib-core-logging')(loggerNamespace, { level: process.env.LOG_LEVEL }) +const coreLogging = require('@adobe/aio-lib-core-logging') const originalFetch = require('node-fetch') const { codes } = require('./SDKErrors') const { HttpProxyAgent } = require('http-proxy-agent') @@ -42,42 +42,44 @@ class PatchedHttpsProxyAgent extends HttpsProxyAgent { * @private * * @param {string} resourceUrl an endpoint url for proxyAgent selection - * @param {ProxyAuthOptions} proxyOptions an object which contains auth information + * @param {ProxyOptions} proxyOptions an object which contains proxy information + * @param {object} logger the logger instance * @returns {http.Agent} a http.Agent for basic auth proxy */ -function proxyAgent (resourceUrl, proxyAuthOptions) { +function proxyAgent (resourceUrl, proxyOptions, logger) { if (typeof resourceUrl !== 'string') { throw new codes.ERROR_PROXY_FETCH_INITIALIZATION_TYPE({ sdkDetails: { resourceUrl }, messageValues: 'resourceUrl must be of type string' }) } - const { proxyUrl, username, password, rejectUnauthorized = true } = proxyAuthOptions - const proxyOpts = urlToHttpOptions(proxyUrl) + const { proxyUrl, username, password, rejectUnauthorized = true } = proxyOptions + const proxyHttpOptions = urlToHttpOptions(proxyUrl) - if (!proxyOpts.auth && username && password) { + if (!proxyHttpOptions.auth && username && password) { logger.debug('username and password not set in proxy url, using credentials passed in the constructor.') - proxyOpts.auth = `${username}:${password}` + proxyHttpOptions.auth = `${username}:${password}` } - proxyOpts.rejectUnauthorized = rejectUnauthorized + proxyHttpOptions.rejectUnauthorized = rejectUnauthorized if (rejectUnauthorized === false) { logger.warn(`proxyAgent - rejectUnauthorized is set to ${rejectUnauthorized}`) } if (resourceUrl.startsWith('https')) { - return new PatchedHttpsProxyAgent(proxyUrl, proxyOpts) + return new PatchedHttpsProxyAgent(proxyUrl, proxyHttpOptions) } else { - return new HttpProxyAgent(proxyUrl, proxyOpts) + return new HttpProxyAgent(proxyUrl, proxyHttpOptions) } } /** * Proxy Auth Options * - * @typedef {object} ProxyAuthOptions + * @typedef {object} ProxyOptions * @property {string} proxyUrl - the proxy's url * @property {string} [username] the username for basic auth * @property {string} [password] the password for basic auth * @property {boolean} rejectUnauthorized - set to false to not reject unauthorized server certs + * @property {string} [logLevel] the log level to use (default: process.env.LOG_LEVEL or 'info') */ /** @@ -87,11 +89,14 @@ class ProxyFetch { /** * Initialize this class with Proxy auth options * - * @param {ProxyAuthOptions} proxyAuthOptions the auth options to connect with + * @param {ProxyOptions} proxyOptions the auth options to connect with */ - constructor (proxyAuthOptions = {}) { - logger.debug(`constructor - authOptions: ${JSON.stringify(proxyAuthOptions)}`) - const { proxyUrl } = proxyAuthOptions + constructor (proxyOptions = {}) { + this.logLevel = proxyOptions.logLevel || process.env.LOG_LEVEL || 'info' + this.logger = coreLogging(loggerNamespace, { level: this.logLevel }) + + this.logger.debug(`constructor - authOptions: ${JSON.stringify(proxyOptions)}`) + const { proxyUrl } = proxyOptions const { auth } = urlToHttpOptions(proxyUrl) if (!proxyUrl) { @@ -100,15 +105,15 @@ class ProxyFetch { } if (!auth) { - logger.debug('constructor: username or password not set, proxy is anonymous.') + this.logger.debug('constructor: username or password not set, proxy is anonymous.') } - this.authOptions = proxyAuthOptions + this.proxyOptions = proxyOptions return this } /** - * Fetch function, using the configured NTLM Auth options. + * Fetch function, using the configured fetch options, and proxy options (set in the constructor). * * @param {string | Request} resource - the url or Request object to fetch from * @param {object} options - the fetch options @@ -117,7 +122,7 @@ class ProxyFetch { async fetch (resource, options = {}) { return originalFetch(resource, { ...options, - agent: proxyAgent(resource, this.authOptions) + agent: proxyAgent(resource, this.proxyOptions, this.logger) }) } } diff --git a/src/utils.js b/src/utils.js index 666337f..d5d8207 100644 --- a/src/utils.js +++ b/src/utils.js @@ -15,29 +15,29 @@ const { getProxyForUrl } = require('proxy-from-env') const loggerNamespace = '@adobe/aio-lib-core-networking/utils' const logger = require('@adobe/aio-lib-core-logging')(loggerNamespace, { level: process.env.LOG_LEVEL }) -/* global ProxyAuthOptions */ +/* global ProxyOptions */ /** * Return the appropriate Fetch function depending on proxy settings. * - * @param {ProxyAuthOptions} [proxyAuthOptions] the proxy auth options + * @param {ProxyOptions} [proxyOptions] the proxy options * @returns {Function} the Fetch API function */ -function createFetch (proxyAuthOptions) { +function createFetch (proxyOptions) { const fn = async (resource, options) => { - // proxyAuthOptions as a parameter will override any proxy env vars - if (!proxyAuthOptions) { + // proxyOptions as a parameter will override any proxy env vars + if (!proxyOptions) { const proxyUrl = getProxyForUrl(resource) if (proxyUrl) { - proxyAuthOptions = { proxyUrl } + proxyOptions = { proxyUrl } } } - if (proxyAuthOptions) { - logger.debug(`createFetch: proxy url found ${proxyAuthOptions.proxyUrl} for url ${resource}`) + if (proxyOptions) { + logger.debug(`createFetch: proxy url found ${proxyOptions.proxyUrl} for url ${resource}`) // in this closure: for fetch-retry, if we don't require it dynamically here, ProxyFetch will be an empty object const ProxyFetch = require('./ProxyFetch') - const proxyFetch = new ProxyFetch(proxyAuthOptions) + const proxyFetch = new ProxyFetch(proxyOptions) return proxyFetch.fetch(resource, options) } else { logger.debug('createFetch: proxy url not found, using plain fetch') diff --git a/test/HttpExponentialBackoff.test.js b/test/HttpExponentialBackoff.test.js index 8d5ab29..d74e99f 100644 --- a/test/HttpExponentialBackoff.test.js +++ b/test/HttpExponentialBackoff.test.js @@ -153,6 +153,53 @@ test('exponentialBackoff with 3 retries on errors with default retry strategy an const result = await fetchClient.exponentialBackoff('https://abc2.com/', { method: 'GET' }, { maxRetries: 2 }) expect(result.status).toBe(503) expect(spy).toHaveBeenCalledTimes(2) + spy.mockRestore() +}) + +test('exponentialBackoff with 2 retries on errors with numeric Retry-After header', async () => { + const retrySpy = jest.spyOn(fetchClient, '__getRetryDelayWithRetryAfterHeader') + fetchMock.mockResponse('429 Too Many Requests', { + status: 429, + headers: { + 'Retry-After': '5' + } + }) + const result = await fetchClient.exponentialBackoff('https://abc3.com/', { method: 'GET' }, { maxRetries: 2, initialDelayInMillis: 100 }) + expect(result.status).toBe(429) + expect(retrySpy).toHaveBeenCalledWith(100) + retrySpy.mockRestore() +}) + +test('exponentialBackoff falls back to exponential backoff when Retry-After header is not present', async () => { + const retrySpy = jest.spyOn(fetchClient, '__getRetryDelayWithRetryAfterHeader') + const retryDelaySpy = jest.spyOn(fetchClient, '__getRetryDelay') + fetchMock.mockResponse('503 Service Unavailable', { + status: 503, + headers: {} + }) + const result = await fetchClient.exponentialBackoff('https://abc4.com/', { method: 'GET' }, { maxRetries: 2, initialDelayInMillis: 50 }) + expect(result.status).toBe(503) + expect(retrySpy).toHaveBeenCalledWith(50) + expect(retryDelaySpy).toHaveBeenCalled() + retrySpy.mockRestore() + retryDelaySpy.mockRestore() +}) + +test('exponentialBackoff falls back to exponential backoff when Retry-After header is invalid', async () => { + const retrySpy = jest.spyOn(fetchClient, '__getRetryDelayWithRetryAfterHeader') + const retryDelaySpy = jest.spyOn(fetchClient, '__getRetryDelay') + fetchMock.mockResponse('503 Service Unavailable', { + status: 503, + headers: { + 'Retry-After': 'invalid' + } + }) + const result = await fetchClient.exponentialBackoff('https://abc5.com/', { method: 'GET' }, { maxRetries: 2, initialDelayInMillis: 50 }) + expect(result.status).toBe(503) + expect(retrySpy).toHaveBeenCalledWith(50) + expect(retryDelaySpy).toHaveBeenCalled() + retrySpy.mockRestore() + retryDelaySpy.mockRestore() }) test('exponential backoff with success in first attempt and custom retryOptions', async () => { diff --git a/types.d.ts b/types.d.ts index 4f22424..3dcec83 100644 --- a/types.d.ts +++ b/types.d.ts @@ -7,15 +7,18 @@ declare type RetryOptions = { maxRetries: number; initialDelayInMillis: number; - proxy: ProxyAuthOptions; + proxy: ProxyOptions; }; /** - * This class provides methods to implement fetch with retries. - * The retries use exponential backoff strategy - * with defaults set to max of 3 retries and initial Delay as 100ms + * Creates an instance of HttpExponentialBackoff + * @param [options] - configuration options + * @param [options.logLevel] - the log level to use (default: process.env.LOG_LEVEL or 'info') */ declare class HttpExponentialBackoff { + constructor(options?: { + logLevel?: string; + }); /** * This function will retry connecting to a url end-point, with * exponential backoff. Returns a Promise. @@ -35,20 +38,22 @@ declare class HttpExponentialBackoff { * @property [username] - the username for basic auth * @property [password] - the password for basic auth * @property rejectUnauthorized - set to false to not reject unauthorized server certs + * @property [logLevel] - the log level to use (default: process.env.LOG_LEVEL or 'info') */ -declare type ProxyAuthOptions = { +declare type ProxyOptions = { proxyUrl: string; username?: string; password?: string; rejectUnauthorized: boolean; + logLevel?: string; }; /** * Initialize this class with Proxy auth options - * @param proxyAuthOptions - the auth options to connect with + * @param proxyOptions - the auth options to connect with */ declare class ProxyFetch { - constructor(proxyAuthOptions: ProxyAuthOptions); + constructor(proxyOptions: ProxyOptions); /** * Fetch function, using the configured NTLM Auth options. * @param resource - the url or Request object to fetch from @@ -60,10 +65,10 @@ declare class ProxyFetch { /** * Return the appropriate Fetch function depending on proxy settings. - * @param [proxyAuthOptions] - the proxy auth options + * @param [proxyOptions] - the proxy options * @returns the Fetch API function */ -declare function createFetch(proxyAuthOptions?: ProxyAuthOptions): (...params: any[]) => any; +declare function createFetch(proxyOptions?: ProxyOptions): (...params: any[]) => any; /** * Parse the Retry-After header From a985abb217d7f8980ffcc3f23d710cac029760c5 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah <36107+shazron@users.noreply.github.com> Date: Thu, 13 Nov 2025 16:00:38 +0800 Subject: [PATCH 2/3] fix: for HttpExponentialBackoff, add logRetryAfterSeconds option This will log a warning if the Retry-After header is greater than logRetryAfterSeconds. Set to 0 to disable. --- src/HttpExponentialBackoff.js | 17 ++++++++---- test/HttpExponentialBackoff.test.js | 42 +++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/src/HttpExponentialBackoff.js b/src/HttpExponentialBackoff.js index b8dc4c0..e17619f 100644 --- a/src/HttpExponentialBackoff.js +++ b/src/HttpExponentialBackoff.js @@ -37,10 +37,12 @@ class HttpExponentialBackoff { * * @param {object} [options] configuration options * @param {string} [options.logLevel] the log level to use (default: process.env.LOG_LEVEL or 'info') + * @param {number} [options.logRetryAfterSeconds] the number of seconds after which to log a warning if the Retry-After header is greater than the number of seconds. Set to 0 to disable. */ constructor (options = {}) { this.logLevel = options.logLevel || process.env.LOG_LEVEL || 'info' this.logger = coreLogging(loggerNamespace, { level: this.logLevel }) + this.logRetryAfterSeconds = options.logRetryAfterSeconds } /** @@ -131,7 +133,7 @@ class HttpExponentialBackoff { * @private */ __getRetryDelay (initialDelayInMillis) { - return (attempt, error, response) => { + return (attempt, _error, _response) => { const timeToWait = Math.pow(2, attempt) * initialDelayInMillis // 1000, 2000, 4000 const msg = `Request will be retried after ${timeToWait} ms` this.logger.debug(msg) @@ -151,10 +153,15 @@ class HttpExponentialBackoff { __getRetryDelayWithRetryAfterHeader (initialDelayInMillis) { return (attempt, error, response) => { const retryAfter = response?.headers.get('Retry-After') || null - const timeToWait = parseRetryAfterHeader(retryAfter) - if (!isNaN(timeToWait)) { - this.logger.debug(`Request will be retried after ${timeToWait} ms`) - return timeToWait + const timeToWaitMs = parseRetryAfterHeader(retryAfter) + if (!isNaN(timeToWaitMs)) { + const message = `Request will be retried after ${timeToWaitMs} ms` + if (this.logRetryAfterSeconds && timeToWaitMs > (this.logRetryAfterSeconds * 1000)) { + this.logger.warn(message) + } else { + this.logger.debug(message) + } + return timeToWaitMs } return this.__getRetryDelay(initialDelayInMillis)(attempt, error, response) } diff --git a/test/HttpExponentialBackoff.test.js b/test/HttpExponentialBackoff.test.js index d74e99f..e9ca10d 100644 --- a/test/HttpExponentialBackoff.test.js +++ b/test/HttpExponentialBackoff.test.js @@ -319,3 +319,45 @@ test('exponentialBackoff fetch throws', async () => { fetchClient.exponentialBackoff('https://abc1.com/', { method: 'GET' }) ).rejects.toThrow('this is a fetch error, no response is defined') }) + +test('exponentialBackoff with 2 retries logs warning when Retry-After exceeds logRetryAfterSeconds', async () => { + const fetchClientWithLogRetryAfter = new HttpExponentialBackoff({ logRetryAfterSeconds: 3 }) + const warnSpy = jest.spyOn(fetchClientWithLogRetryAfter.logger, 'warn') + const debugSpy = jest.spyOn(fetchClientWithLogRetryAfter.logger, 'debug') + + fetchMock.mockResponse('429 Too Many Requests', { + status: 429, + headers: { + 'Retry-After': '5' // 5 seconds, which is > 3 seconds threshold + } + }) + + const result = await fetchClientWithLogRetryAfter.exponentialBackoff('https://abc6.com/', { method: 'GET' }, { maxRetries: 2, initialDelayInMillis: 100 }) + expect(result.status).toBe(429) + expect(warnSpy).toHaveBeenCalledWith('Request will be retried after 5000 ms') + expect(debugSpy).not.toHaveBeenCalledWith('Request will be retried after 5000 ms') + + warnSpy.mockRestore() + debugSpy.mockRestore() +}) + +test('exponentialBackoff with 2 retries logs debug when Retry-After is below logRetryAfterSeconds', async () => { + const fetchClientWithLogRetryAfter = new HttpExponentialBackoff({ logRetryAfterSeconds: 10 }) + const warnSpy = jest.spyOn(fetchClientWithLogRetryAfter.logger, 'warn') + const debugSpy = jest.spyOn(fetchClientWithLogRetryAfter.logger, 'debug') + + fetchMock.mockResponse('429 Too Many Requests', { + status: 429, + headers: { + 'Retry-After': '5' // 5 seconds, which is < 10 seconds threshold + } + }) + + const result = await fetchClientWithLogRetryAfter.exponentialBackoff('https://abc7.com/', { method: 'GET' }, { maxRetries: 2, initialDelayInMillis: 100 }) + expect(result.status).toBe(429) + expect(debugSpy).toHaveBeenCalledWith('Request will be retried after 5000 ms') + expect(warnSpy).not.toHaveBeenCalledWith('Request will be retried after 5000 ms') + + warnSpy.mockRestore() + debugSpy.mockRestore() +}) From d05c6fb4a210a55225aae35623e3b21a80817634 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah <36107+shazron@users.noreply.github.com> Date: Thu, 13 Nov 2025 18:02:20 +0800 Subject: [PATCH 3/3] update docs --- README.md | 3 ++- types.d.ts | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fa3856c..bdd4272 100644 --- a/README.md +++ b/README.md @@ -134,6 +134,7 @@ Creates an instance of HttpExponentialBackoff | --- | --- | --- | | [options] | object | configuration options | | [options.logLevel] | string | the log level to use (default: process.env.LOG_LEVEL or 'info') | +| [options.logRetryAfterSeconds] | number | the number of seconds after which to log a warning if the Retry-After header is greater than the number of seconds. Set to 0 to disable. | @@ -176,7 +177,7 @@ Initialize this class with Proxy auth options ### proxyFetch.fetch(resource, options) ⇒ Promise.<Response> -Fetch function, using the configured NTLM Auth options. +Fetch function, using the configured fetch options, and proxy options (set in the constructor). **Kind**: instance method of [ProxyFetch](#ProxyFetch) **Returns**: Promise.<Response> - Promise object representing the http response diff --git a/types.d.ts b/types.d.ts index 3dcec83..50de1a9 100644 --- a/types.d.ts +++ b/types.d.ts @@ -14,10 +14,12 @@ declare type RetryOptions = { * Creates an instance of HttpExponentialBackoff * @param [options] - configuration options * @param [options.logLevel] - the log level to use (default: process.env.LOG_LEVEL or 'info') + * @param [options.logRetryAfterSeconds] - the number of seconds after which to log a warning if the Retry-After header is greater than the number of seconds. Set to 0 to disable. */ declare class HttpExponentialBackoff { constructor(options?: { logLevel?: string; + logRetryAfterSeconds?: number; }); /** * This function will retry connecting to a url end-point, with @@ -55,7 +57,7 @@ declare type ProxyOptions = { declare class ProxyFetch { constructor(proxyOptions: ProxyOptions); /** - * Fetch function, using the configured NTLM Auth options. + * Fetch function, using the configured fetch options, and proxy options (set in the constructor). * @param resource - the url or Request object to fetch from * @param options - the fetch options * @returns Promise object representing the http response