zaccl
Version:
The Zoom App Complete Connection Library, a project that handles everything required to build a zoom-integrated app.
115 lines (103 loc) • 3.04 kB
text/typescript
// Import libs
import axios from 'axios';
import qs from 'qs';
// Import ZACCLError
import ZACCLError from '../classes/ZACCLError';
// Import shared types
import ErrorCode from '../types/ErrorCode';
/**
* Sends and retries an http request
* @author Gabe Abrams
* @param {string} host host to send request to
* @param {string} path path to send request to
* @param {string} [method=GET] http method to use
* @param {object} [params] body/data to include in the request
* @param {object} [headers] headers to include in the request
* @param {number} [numRetries=0] number of times to retry the request if it
* fails
* @returns { body, status, headers } on
* success
*/
const sendRequest = async (
opts: {
host: string,
path: string,
method: ('GET' | 'POST' | 'PUT' | 'DELETE'),
params?: { [k: string]: any },
headers?: { [k: string]: string },
numRetries?: number,
},
): Promise<{
body: any,
status: number,
headers: { [k: string]: string },
}> => {
// Set max number of retries if not defined
const numRetries = (opts.numRetries ?? 0);
// Use default method if applicable
const method = (opts.method ?? 'GET');
// Stringify parameters
const stringifiedParams = qs.stringify(
opts.params ?? {},
{
encodeValuesOnly: true,
arrayFormat: 'brackets',
},
);
// Create url (include query if GET)
const query = (method === 'GET' ? `?${stringifiedParams}` : '');
let url;
if (!opts.host) {
// No host included at all. Just send to a path
url = `${opts.path}${query.length > 1 ? query : ''}`;
} else {
url = `https://${opts.host}${opts.path}${query.length > 1 ? query : ''}`;
}
// Update headers
const headers = opts.headers || {};
if (!headers['Content-Type']) {
// Form encoded
headers['Content-Type'] = 'application/json';
}
// Send request
try {
const response = await axios({
method,
url,
headers,
data: opts.params,
});
// Only return part of the axios response
return {
body: response.data,
status: response.status,
headers: response.headers,
};
} catch (err) {
// Axios throws an error if the request status indicates an error
// sendRequest is supposed to resolve if the request went through, whether
// the status indicates an error or not.
if (err.response) {
// Resolve with response
return Promise.resolve({
body: err.response.data,
status: err.response.status,
headers: err.response.headers,
});
}
// Request failed! Check if we have more attempts
if (numRetries > 0) {
// Update options with one less retry
return sendRequest({
...opts,
numRetries: numRetries - 1,
});
}
// No tries left
throw new ZACCLError({
message: 'We encountered an error when trying to send a network request. If this issue persists, contact an admin.',
code: ErrorCode.NetworkError,
});
}
};
export default sendRequest;