@openshift-console/dynamic-plugin-sdk
Version:
Provides core APIs, types and utilities used by dynamic plugins at runtime.
137 lines (136 loc) • 6.22 kB
JavaScript
import * as _ from 'lodash';
import { getUtilsConfig } from '../../app/configSetup';
import { setAdmissionWebhookWarning } from '../../app/core/actions';
import storeHandler from '../../app/storeHandler';
import { TimeoutError } from '../error/http-error';
import { getConsoleRequestHeaders } from './console-fetch-utils';
/**
* A custom wrapper around `fetch` that adds console-specific headers and allows for retries and timeouts.
* It also validates the response status code and throws an appropriate error or logs out the user if required.
* @param url The URL to fetch
* @param options The options to pass to fetch
* @param timeout The timeout in milliseconds
* @returns A promise that resolves to the response.
*/
export const consoleFetch = async (url, options = {}, timeout = 60000) => {
const fetchPromise = getUtilsConfig().appFetch(url, options);
if (timeout <= 0) {
return fetchPromise;
}
const timeoutPromise = new Promise((resolve, reject) => {
setTimeout(() => reject(new TimeoutError(url, timeout)), timeout);
});
return Promise.race([fetchPromise, timeoutPromise]);
};
const parseData = async (response) => {
const text = await response.text();
const isPlainText = response.headers.get('Content-Type') === 'text/plain';
if (!text) {
return isPlainText ? '' : {};
}
return isPlainText || !response.ok ? text : JSON.parse(text);
};
const handleAdmissionWebhookWarning = (warning, kind, name) => {
const store = storeHandler.getStore();
const id = `${kind}_${name}_${warning}`;
const warningData = { kind, name, warning };
store.dispatch(setAdmissionWebhookWarning(id, warningData));
};
const consoleFetchCommon = async (url, method = 'GET', options = {}, timeout) => {
const headers = getConsoleRequestHeaders();
// Pass headers last to let callers to override Accept.
const allOptions = _.defaultsDeep({ method }, options, { headers });
const response = await consoleFetch(url, allOptions, timeout);
const dataPromise = parseData(response);
const warning = response.headers.get('Warning');
// If the response has a warning header, store it in the redux store.
if (response.ok && warning && method !== 'GET') {
// Do nothing on error since this is a side-effect. Caller will handle the error.
dataPromise
.then((data) => handleAdmissionWebhookWarning(warning, data.kind, data.metadata?.name))
.catch(() => { });
}
return dataPromise;
};
/**
* A custom wrapper around `fetch` that adds console-specific headers and allows for retries and timeouts.
* It also validates the response status code and throws an appropriate error or logs out the user if required.
* It returns the response as a JSON object.
* Uses consoleFetch internally.
* @param url The URL to fetch
* @param method The HTTP method to use. Defaults to GET
* @param options The options to pass to fetch
* @param timeout The timeout in milliseconds
* @returns A promise that resolves to the response as text or JSON object.
*/
export const consoleFetchJSON = (url, method = 'GET', options = {}, timeout) => {
const allOptions = _.defaultsDeep({}, options, {
headers: { Accept: 'application/json' },
});
return consoleFetchCommon(url, method, allOptions, timeout);
};
/**
* A custom wrapper around `fetch` that adds console-specific headers and allows for retries and timeouts.
* It also validates the response status code and throws an appropriate error or logs out the user if required.
* It returns the response as a text.
* Uses `consoleFetch` internally.
* @param url The URL to fetch
* @param options The options to pass to fetch
* @param timeout The timeout in milliseconds
* @returns A promise that resolves to the response as text or JSON object.
*/
export const consoleFetchText = (url, options = {}, timeout) => {
return consoleFetchCommon(url, 'GET', options, timeout);
};
const consoleFetchSendJSON = (url, method, json = null, options = {}, timeout) => {
const allOptions = {
headers: {
Accept: 'application/json',
'Content-Type': `application/${method === 'PATCH' ? 'json-patch+json' : 'json'};charset=UTF-8`,
},
};
if (json) {
allOptions.body = JSON.stringify(json);
}
return consoleFetchJSON(url, method, _.defaultsDeep(allOptions, options), timeout);
};
/**
* A custom DELETE method of consoleFetchJSON.
* It sends an optional JSON object as the body of the request and adds extra headers for patch request.
* @param url The URL to delete the object
* @param json The JSON to delete the object
* @param options The options to pass to fetch
* @param timeout The timeout in milliseconds
*/
consoleFetchJSON.delete = (url, json = null, options = {}, timeout) => {
return json
? consoleFetchSendJSON(url, 'DELETE', json, options, timeout)
: consoleFetchJSON(url, 'DELETE', options, timeout);
};
/**
* A custom POST method of consoleFetchJSON.
* It sends the JSON object as the body of the request.
* @param url The URL to post the object
* @param json The JSON to POST the object
* @param options The options to pass to fetch
* @param timeout The timeout in milliseconds
*/
consoleFetchJSON.post = (url, json, options = {}, timeout) => consoleFetchSendJSON(url, 'POST', json, options, timeout);
/**
* A custom PUT method of consoleFetchJSON.
* It sends the JSON object as the body of the request.
* @param url The URL to put the object
* @param json The JSON to PUT the object
* @param options The options to pass to fetch
* @param timeout The timeout in milliseconds
*/
consoleFetchJSON.put = (url, json, options = {}, timeout) => consoleFetchSendJSON(url, 'PUT', json, options, timeout);
/**
* A custom PATCH method of consoleFetchJSON.
* It sends the JSON object as the body of the request.
* @param url The URL to patch the object
* @param json The JSON to PATCH the object
* @param options The options to pass to fetch
* @param timeout The timeout in milliseconds
*/
consoleFetchJSON.patch = (url, json, options = {}, timeout) => consoleFetchSendJSON(url, 'PATCH', json, options, timeout);