UNPKG

serverless-api-gateway-throttling

Version:

A plugin for the Serverless framework which configures throttling for API Gateway endpoints.

112 lines (95 loc) 3.85 kB
const isEmpty = require('lodash.isempty'); const { retrieveRestApiId } = require('./restApiId'); const { httpEventOf, patchPathFor } = require('./lib'); const MAX_PATCH_OPERATIONS_PER_STAGE_UPDATE = 80; const updateRestApi = async (settings, serverless) => { const restApiId = await retrieveRestApiId(serverless, settings); let restApiPatchOps = createPatchForStage(settings); for (const restEndpointSettings of settings.restEndpointSettings) { const endpointPatch = createPatchForRestEndpoint(restEndpointSettings, serverless); restApiPatchOps = restApiPatchOps.concat(endpointPatch); } const { stage, region } = settings; const params = { restApiId, stageName: stage, patchOperations: restApiPatchOps } await updateStageFor(serverless, params, stage, region); } const updateStageFor = async (serverless, params, stage, region) => { const chunkSize = MAX_PATCH_OPERATIONS_PER_STAGE_UPDATE; const { patchOperations } = params; const paramsInChunks = []; if (patchOperations.length > chunkSize) { for (let i = 0; i < patchOperations.length; i += chunkSize) { paramsInChunks.push({ restApiId: params.restApiId, stageName: params.stageName, patchOperations: patchOperations.slice(i, i + chunkSize) }); } } else { paramsInChunks.push(params); } for (let index in paramsInChunks) { serverless.cli.log(`[serverless-api-gateway-throttling] Updating API Gateway REST API throttling settings (${parseInt(index) + 1} of ${paramsInChunks.length}).`); await serverless.providers.aws.request('APIGateway', 'updateStage', paramsInChunks[index], stage, region); } serverless.cli.log(`[serverless-api-gateway-throttling] Done updating API Gateway REST API throttling settings.`); } const createPatchForRestEndpoint = (endpointSettings, serverless) => { let lambda = serverless.service.getFunction(endpointSettings.functionName); if (isEmpty(lambda.events)) { serverless.cli.log(`[serverless-api-gateway-throttling] Lambda ${endpointSettings.functionName} has not defined events.`); return; } const httpEvent = httpEventOf(lambda, endpointSettings); if (isEmpty(httpEvent)) { serverless.cli.log(`[serverless-api-gateway-throttling] Lambda ${endpointSettings.functionName} has not defined any HTTP events.`); return; } let { path, method } = httpEvent; let patch = []; if (method.toUpperCase() == 'ANY') { let httpMethodsToConfigureThrottlingFor = ['GET', 'DELETE', 'HEAD', 'OPTIONS', 'PATCH', 'POST', 'PUT']; for (let methodWithThrottlingSettings of httpMethodsToConfigureThrottlingFor) { patch = patch.concat(patchForMethod(path, methodWithThrottlingSettings, endpointSettings)); }; } else { patch = patch.concat(patchForMethod(path, method, endpointSettings)); } return patch; } const createPatchForStage = (settings) => { let patch = [{ op: 'replace', path: '/*/*/throttling/rateLimit', value: `${settings.maxRequestsPerSecond}` }, { op: 'replace', path: '/*/*/throttling/burstLimit', value: `${settings.maxConcurrentRequests}` }]; return patch; } const patchForMethod = (path, method, endpointSettings) => { let patchPath = patchPathFor(path, method); let patch = [{ op: 'replace', path: `/${patchPath}/throttling/rateLimit`, value: `${endpointSettings.maxRequestsPerSecond}` }, { op: 'replace', path: `/${patchPath}/throttling/burstLimit`, value: `${endpointSettings.maxConcurrentRequests}` }] return patch; } module.exports = { updateRestApi }