@atlaskit/util-service-support
Version:
A library of support classes for integrating React components with REST HTTP services
80 lines (77 loc) • 2.8 kB
JavaScript
import { getActiveTraceHttpRequestHeaders } from '@atlaskit/react-ufo/experience-trace-id-context';
import { buildCredentials } from './types';
import { defaultRequestServiceOptions, buildUrl, buildHeaders } from './shared';
const TRACING_RESPONSE_HEADERS = ['x-trace-id', 'atl-request-id'];
/**
* Extracts tracing headers (x-trace-id, atl-request-id) from a Response object.
* Returns only headers that are present in the response.
*/
export const extractTracingHeaders = response => {
const headers = {};
for (const name of TRACING_RESPONSE_HEADERS) {
const value = response.headers.get(name);
if (value) {
headers[name] = value;
}
}
return headers;
};
/**
* @returns Promise containing the json response
*/
export const requestService = (serviceConfig, options) => {
const {
url,
securityProvider,
refreshedSecurityProvider
} = serviceConfig;
const {
path,
queryParams,
requestInit
} = options || defaultRequestServiceOptions;
const secOptions = securityProvider && securityProvider();
const requestUrl = buildUrl(url, path, queryParams, secOptions);
const headers = buildHeaders(secOptions, requestInit && requestInit.headers);
const credentials = buildCredentials(secOptions);
const ignoreResponsePayload = (options === null || options === void 0 ? void 0 : options.ignoreResponsePayload) || false;
// Get tracing headers from UFO
const tracingHeaders = getActiveTraceHttpRequestHeaders(url);
const requestOptions = {
...requestInit,
// populate headers mainly for the collab provider however
// other components which uses this util can get the header as well.
// Those tracing headers shall not incur any issues as long as backends handle them properly
headers: {
...headers,
...tracingHeaders
},
credentials
};
return fetch(requestUrl, requestOptions).then(response => {
if (options !== null && options !== void 0 && options.reportTracingHeaders) {
const tracingHeaders = extractTracingHeaders(response);
if (Object.keys(tracingHeaders).length > 0) {
options.reportTracingHeaders(tracingHeaders);
}
}
if (response.status === 204) {
return Promise.resolve();
} else if (response.ok) {
return ignoreResponsePayload ? Promise.resolve() : response.json();
} else if (response.status === 401 && refreshedSecurityProvider) {
// auth issue - try once
return refreshedSecurityProvider().then(newSecOptions => {
const retryServiceConfig = {
url,
securityProvider: () => newSecOptions
};
return requestService(retryServiceConfig, options);
});
}
return Promise.reject({
code: response.status,
reason: response.statusText
});
});
};