Skip to content

Commit

Permalink
feat: add fetch timeout [INS-3911] (#7467)
Browse files Browse the repository at this point in the history
* remove exponential backoff

* feat: improve err message when time out

---------

Co-authored-by: jackkav <jackkav@gmail.com>
  • Loading branch information
2 people authored and saisatishkarra committed Jun 5, 2024
1 parent b2d3230 commit 6198b92
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 28 deletions.
3 changes: 3 additions & 0 deletions packages/insomnia/src/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -590,3 +590,6 @@ export const EXPORT_TYPE_ENVIRONMENT = 'environment';
export const EXPORT_TYPE_API_SPEC = 'api_spec';
export const EXPORT_TYPE_PROTO_FILE = 'proto_file';
export const EXPORT_TYPE_PROTO_DIRECTORY = 'proto_directory';

// (ms) curently server timeout is 30s
export const INSOMNIA_FETCH_TIME_OUT = 30_000;
45 changes: 17 additions & 28 deletions packages/insomnia/src/ui/insomniaFetch.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@

import { getApiBaseURL, getClientString, PLAYWRIGHT } from '../common/constants';
import { delay } from '../common/misc';
import { getApiBaseURL, getClientString, INSOMNIA_FETCH_TIME_OUT, PLAYWRIGHT } from '../common/constants';

interface FetchConfig {
method: 'POST' | 'PUT' | 'GET' | 'DELETE' | 'PATCH';
Expand All @@ -13,26 +12,6 @@ interface FetchConfig {
headers?: Record<string, string>;
}

const exponentialBackOff = async (url: string, init: RequestInit, retries = 0): Promise<Response> => {
try {
const response = await fetch(url, init);
if (response.status === 502 && retries < 5) {
retries++;
await delay(retries * 1000);
console.log(`Received 502 from ${url} retrying`);
return exponentialBackOff(url, init, retries);
}
if (!response.ok) {
// TODO: review error status code behaviour with backend, should we parse errors here and return response
// or should we rethrow an error with a response object inside? should we be exposing errors to the app UI?
console.log(`Response not OK: ${response.status} for ${url}`);
}
return response;
} catch (err) {
throw err;
}
};

// Adds headers, retries and opens deep links returned from the api
export async function insomniaFetch<T = void>({ method, path, data, sessionId, organizationId, origin, headers }: FetchConfig): Promise<T> {
const config: RequestInit = {
Expand All @@ -47,15 +26,25 @@ export async function insomniaFetch<T = void>({ method, path, data, sessionId, o
...(PLAYWRIGHT ? { 'X-Mockbin-Test': 'true' } : {}),
},
...(data ? { body: JSON.stringify(data) } : {}),
signal: AbortSignal.timeout(INSOMNIA_FETCH_TIME_OUT),
};
if (sessionId === undefined) {
throw new Error(`No session ID provided to ${method}:${path}`);
}
const response = await exponentialBackOff((origin || getApiBaseURL()) + path, config);
const uri = response.headers.get('x-insomnia-command');
if (uri) {
window.main.openDeepLink(uri);

try {
const response = await fetch((origin || getApiBaseURL()) + path, config);
const uri = response.headers.get('x-insomnia-command');
if (uri) {
window.main.openDeepLink(uri);
}
const isJson = response.headers.get('content-type')?.includes('application/json') || path.match(/\.json$/);
return isJson ? response.json() : response.text();
} catch (err) {
if (err.name === 'AbortError') {
throw new Error('insomniaFetch timed out');
} else {
throw err;
}
}
const isJson = response.headers.get('content-type')?.includes('application/json') || path.match(/\.json$/);
return isJson ? response.json() : response.text();
}

0 comments on commit 6198b92

Please sign in to comment.