contentful-sdk-core
Version:
Core modules for the Contentful JS SDKs
65 lines (64 loc) • 2.54 kB
JavaScript
import isString from 'lodash/isString.js';
import pThrottle from 'p-throttle';
import { noop } from './utils.js';
const PERCENTAGE_REGEX = /(?<value>\d+)(%)/;
function calculateLimit(type, max = 7) {
let limit = max;
if (PERCENTAGE_REGEX.test(type)) {
const groups = type.match(PERCENTAGE_REGEX)?.groups;
if (groups && groups.value) {
const percentage = parseInt(groups.value) / 100;
limit = Math.round(max * percentage);
}
}
return Math.min(30, Math.max(1, limit));
}
function createThrottle(limit, logger) {
logger('info', `Throttle request to ${limit}/s`);
return pThrottle({
limit,
interval: 1000,
strict: false,
});
}
export default (axiosInstance, type = 'auto') => {
const { logHandler = noop } = axiosInstance.defaults;
let limit = isString(type) ? calculateLimit(type) : calculateLimit('auto', type);
let throttle = createThrottle(limit, logHandler);
let isCalculated = false;
let requestInterceptorId = axiosInstance.interceptors.request.use((config) => {
return throttle(() => config)();
}, function (error) {
return Promise.reject(error);
});
const responseInterceptorId = axiosInstance.interceptors.response.use((response) => {
if (!isCalculated &&
isString(type) &&
(type === 'auto' || PERCENTAGE_REGEX.test(type)) &&
response.headers &&
response.headers['x-contentful-ratelimit-second-limit']) {
const rawLimit = parseInt(response.headers['x-contentful-ratelimit-second-limit']);
const nextLimit = calculateLimit(type, rawLimit);
if (nextLimit !== limit) {
if (requestInterceptorId) {
axiosInstance.interceptors.request.eject(requestInterceptorId);
}
limit = nextLimit;
throttle = createThrottle(nextLimit, logHandler);
requestInterceptorId = axiosInstance.interceptors.request.use((config) => {
return throttle(() => config)();
}, function (error) {
return Promise.reject(error);
});
}
isCalculated = true;
}
return response;
}, function (error) {
return Promise.reject(error);
});
return () => {
axiosInstance.interceptors.request.eject(requestInterceptorId);
axiosInstance.interceptors.response.eject(responseInterceptorId);
};
};