import { IRequestOptions, IResponse, ISecureSplitHttpClient, NetworkError } from './types'; import { ISettings } from '../types'; import { IPlatform } from '../sdkFactory/types'; import { splitHttpClientFactory } from './splitHttpClient'; import { authProviderFactory } from './authProvider'; import { ITelemetryTracker } from '../trackers/types'; /** * Factory of Secure HTTP client, which authenticates requests using a JWT token. * On 401 responses, invalidates the cached credential and retries once with a fresh token. * * @param settings - SDK settings * @param platform - object containing environment-specific dependencies * @param fetchAuth - function to fetch auth credentials from the /v2/auth endpoint */ export function secureSplitHttpClientFactory(settings: ISettings, platform: Pick, telemetryTracker: ITelemetryTracker): ISecureSplitHttpClient { const splitHttpClient = splitHttpClientFactory(settings, platform); const authProvider = authProviderFactory(settings, splitHttpClient, telemetryTracker); function makeRequest(url: string, options: IRequestOptions | undefined, latencyTracker: ((error?: NetworkError) => void) | undefined, logErrorsAsInfo: boolean | undefined, token: string): Promise { return splitHttpClient(url, { ...options, headers: { ...options?.headers, Authorization: `Bearer ${token}` } }, latencyTracker, logErrorsAsInfo, true); } const httpClient = function (url: string, options?: IRequestOptions, latencyTracker?: (error?: NetworkError) => void, logErrorsAsInfo?: boolean): Promise { return authProvider.credential().then(credential => { return makeRequest(url, options, latencyTracker, logErrorsAsInfo, credential.token) .catch((error: NetworkError) => { if (error.statusCode === 401) { // retry once for 401, in case the token has just expired authProvider.invalidate(); return authProvider.credential().then(newCredential => { return makeRequest(url, options, latencyTracker, logErrorsAsInfo, newCredential.token); }); } throw error; }); }); }; httpClient.stop = () => authProvider.stop(); return httpClient; }