diff --git a/.changeset/polite-loops-cross.md b/.changeset/polite-loops-cross.md new file mode 100644 index 0000000..16fa95e --- /dev/null +++ b/.changeset/polite-loops-cross.md @@ -0,0 +1,5 @@ +--- +'fetch-nodeshim': patch +--- + +Add configurable `connectTimeout` to override connection timeout. The default will now also be 30s if the request contains `text/html` in the `Accept` header diff --git a/src/__tests__/fetch.test.ts b/src/__tests__/fetch.test.ts index 65fcada..3b652bd 100644 --- a/src/__tests__/fetch.test.ts +++ b/src/__tests__/fetch.test.ts @@ -67,6 +67,12 @@ describe(fetch, () => { await expect(() => fetch('http://localhost:50000/')).rejects.toThrow(); }, 1_000); + it('should reject with error when connectTimeout is exceeded', async () => { + await expect(() => + fetch('http://10.255.255.1/', { connectTimeout: 100 }) + ).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: Request timed out]`); + }, 5_000); + it('should resolve into response', async () => { const response = await fetch(new URL('hello', baseURL)); expect(response.url).toBe(`${baseURL}hello`); diff --git a/src/fetch.ts b/src/fetch.ts index 09b0e33..374b1dd 100644 --- a/src/fetch.ts +++ b/src/fetch.ts @@ -163,9 +163,15 @@ async function _fetch( const requestHeaders = new Headers( init?.headers ?? (initFromRequest ? input.headers : undefined) ); + + let DEFAULT_TIMEOUT = 5_000; + if (requestHeaders.get('accept')?.includes('text/html')) { + DEFAULT_TIMEOUT = 30_000; + } + const requestOptions = { ...urlToHttpOptions(requestUrl), - timeout: 5_000, + timeout: init?.connectTimeout ?? DEFAULT_TIMEOUT, method: methodToHttpOption(initFromRequest ? input.method : init?.method), signal, } satisfies http.RequestOptions; diff --git a/src/webstd.ts b/src/webstd.ts index c70eae6..88078d3 100644 --- a/src/webstd.ts +++ b/src/webstd.ts @@ -56,6 +56,7 @@ if (typeof globalThis.File === 'undefined') { // Here, we have to account for global differences and split the overloads apart interface _RequestInit extends Or { + connectTimeout?: number; duplex?: 'half'; } interface _ResponseInit extends Or {}