mattermost-mobile/app/managers/network_manager.ts
Jason Frerich 4dfb9fb60c
[Gekidou MM-45178] Improve wording about url not being a valid one (#6449)
* if the API client returns and error, throw a new error with better
  descriptive text for the user

* add intl to message

* move happy path code into try block
2022-08-05 14:12:01 +04:00

134 lines
4.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import Emm from '@mattermost/react-native-emm';
import {
APIClientErrorEvent,
APIClientErrorEventHandler,
getOrCreateAPIClient,
RetryTypes,
} from '@mattermost/react-native-network-client';
import {DeviceEventEmitter} from 'react-native';
import UserAgent from 'react-native-user-agent';
import LocalConfig from '@assets/config.json';
import {Client} from '@client/rest';
import * as ClientConstants from '@client/rest/constants';
import ClientError from '@client/rest/error';
import {CERTIFICATE_ERRORS} from '@constants/network';
import ManagedApp from '@init/managed_app';
import {logError} from '@utils/log';
import {getCSRFFromCookie} from '@utils/security';
import type {ServerCredential} from '@typings/credentials';
const CLIENT_CERTIFICATE_IMPORT_ERROR_CODES = [-103, -104, -105, -108];
const CLIENT_CERTIFICATE_MISSING_ERROR_CODE = -200;
class NetworkManager {
private clients: Record<string, Client> = {};
private DEFAULT_CONFIG = {
headers: {
'X-Requested-With': 'XMLHttpRequest',
...LocalConfig.CustomRequestHeaders,
},
sessionConfiguration: {
allowsCellularAccess: true,
waitsForConnectivity: false,
timeoutIntervalForRequest: 30000,
timeoutIntervalForResource: 30000,
httpMaximumConnectionsPerHost: 10,
cancelRequestsOnUnauthorized: true,
},
retryPolicyConfiguration: {
type: RetryTypes.EXPONENTIAL_RETRY,
retryLimit: 3,
exponentialBackoffBase: 2,
exponentialBackoffScale: 0.5,
},
requestAdapterConfiguration: {
bearerAuthTokenResponseHeader: 'token',
},
};
public init = async (serverCredentials: ServerCredential[]) => {
for await (const {serverUrl, token} of serverCredentials) {
try {
await this.createClient(serverUrl, token);
} catch (error) {
logError('NetworkManager init error', error);
}
}
};
public invalidateClient = (serverUrl: string) => {
this.clients[serverUrl]?.invalidate();
delete this.clients[serverUrl];
};
public getClient = (serverUrl: string) => {
const client = this.clients[serverUrl];
if (!client) {
throw new Error(`${serverUrl} client not found`);
}
return client;
};
public createClient = async (serverUrl: string, bearerToken?: string) => {
const config = await this.buildConfig();
try {
const {client} = await getOrCreateAPIClient(serverUrl, config, this.clientErrorEventHandler);
const csrfToken = await getCSRFFromCookie(serverUrl);
this.clients[serverUrl] = new Client(client, serverUrl, bearerToken, csrfToken);
} catch (error) {
throw new ClientError(serverUrl, {
message: 'Cant find this server. Check spelling and URL format.',
intl: {
id: 'apps.error.network.no_server',
defaultMessage: 'Cant find this server. Check spelling and URL format.',
},
url: serverUrl,
});
}
return this.clients[serverUrl];
};
private buildConfig = async () => {
const userAgent = UserAgent.getUserAgent();
const headers: Record<string, string> = {
...this.DEFAULT_CONFIG.headers,
[ClientConstants.HEADER_USER_AGENT]: userAgent,
};
const config = {
...this.DEFAULT_CONFIG,
headers,
};
if (ManagedApp.enabled) {
const managedConfig = Emm.getManagedConfig<ManagedConfig>();
if (managedConfig?.useVPN === 'true') {
config.sessionConfiguration.waitsForConnectivity = true;
}
if (managedConfig?.timeoutVPN) {
config.sessionConfiguration.timeoutIntervalForResource = parseInt(managedConfig.timeoutVPN, 10);
}
}
return config;
};
private clientErrorEventHandler: APIClientErrorEventHandler = (event: APIClientErrorEvent) => {
if (CLIENT_CERTIFICATE_IMPORT_ERROR_CODES.includes(event.errorCode)) {
DeviceEventEmitter.emit(CERTIFICATE_ERRORS.CLIENT_CERTIFICATE_IMPORT_ERROR, event.serverUrl);
} else if (CLIENT_CERTIFICATE_MISSING_ERROR_CODE === event.errorCode) {
DeviceEventEmitter.emit(CERTIFICATE_ERRORS.CLIENT_CERTIFICATE_MISSING, event.serverUrl);
}
};
}
export default new NetworkManager();