UNPKG

@akinolae/node-rate-limiter

Version:
127 lines 4.25 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.requestLimitCore = void 0; var Intervals; (function (Intervals) { Intervals[Intervals["Query"] = 60000] = "Query"; Intervals[Intervals["request"] = 10] = "request"; })(Intervals || (Intervals = {})); let requestBucket; const regexCheck = (defaultVal, val) => new RegExp(defaultVal).test(val); const findRequestbyId = (params) => { const { requestIp, functionId } = params; if (!requestIp || !functionId) { throw new Error('INTERVAL_CACHE_ERROR:CallId and functionId is required'); } const requestFromBucket = requestBucket !== undefined ? requestBucket[requestIp] : []; if (Array.isArray(requestFromBucket) && requestFromBucket.length > 0) { for (const interval of requestFromBucket) { if (regexCheck(interval.callID, functionId)) { return { ...interval, requestIp }; } else { return; } } } }; const addRequestToList = (params) => { const { requestIp, requestObject, ...rest } = params; const callidExists = Object.keys(requestBucket || {}).some((id) => id === requestIp); if (!callidExists) { requestBucket = { ...requestBucket, ...rest, [requestIp]: [requestObject], }; } else { const currentInterval = [ ...requestBucket[requestIp].filter((a) => a?.callID !== requestObject.callID), requestObject, ]; requestBucket = { ...requestBucket, [requestIp]: currentInterval, }; } return requestBucket; }; const manageRequestFn = (params) => { const { callIDexists, currentRequestId, urlFn, interval, session } = params; let requestBody; const date = new Date(); if (!callIDexists || !Object.keys(callIDexists).length) { requestBody = { requestIp: currentRequestId, requestObject: { callID: urlFn, request: session, ttl: interval, lastCall: +date, }, }; } else if (callIDexists.request <= 1 && date.getTime() - callIDexists.lastCall > interval) { requestBody = { requestIp: callIDexists.requestIp, requestObject: { callID: callIDexists.callID, request: session, ttl: callIDexists.ttl, lastCall: +date, }, }; } else { if (!callIDexists.request) { throw new Error(`TOO MANY REQUESTS: call ${urlFn} has too many requests try again in ${Math.floor(callIDexists.ttl / 60000)} minute(s)`); } else { const newRequestLimit = callIDexists.request - 1; requestBody = { requestIp: callIDexists.requestIp, requestObject: { callID: callIDexists.callID, request: newRequestLimit, ttl: callIDexists.ttl, lastCall: callIDexists.lastCall, }, }; } } return requestBody; }; const limitCorefn = (args) => { let urlFn; const validUrl = ['graphql']; const { session_no, ttl, request } = args; const reqIsGraphql = validUrl.some((url) => regexCheck(url, request.baseUrl)); if (reqIsGraphql) { const _req = Object.keys(request.body); if (_req.some((val) => ['query'].includes(val.toLocaleLowerCase()))) { urlFn = request.body[_req[0]].trimStart().split(' ')[1].split('(')[0]; } } else { urlFn = request.url; } const interval = ttl ?? Intervals.Query; const session = session_no ?? Intervals.request; const currentRequestId = `${request.ip}-${urlFn}`; const callIDexists = findRequestbyId({ requestIp: currentRequestId, functionId: urlFn, }); const requestBody = manageRequestFn({ callIDexists, currentRequestId, interval, session, urlFn, }); addRequestToList(requestBody); }; exports.requestLimitCore = limitCorefn; //# sourceMappingURL=index.js.map