UNPKG

flamesshield-sdk

Version:

Flames Shield Smart rate limiting for Firebase Cloud Functions to protect your services from excessive requests

105 lines (104 loc) 4.79 kB
"use strict"; // index.ts var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.rateLimit = void 0; const rate_limiter_1 = require("./rate_limiter"); const remote_1 = require("./remote"); const rate_limiting_enabled_1 = require("./rate_limiting_enabled"); const configuration_retriever_1 = require("./configuration_retriever"); const version_1 = require("./version"); // Import from the auto-generated version file const checkAndUpdateQuota = (limiter) => __awaiter(void 0, void 0, void 0, function* () { const apiKey = limiter.apiKey || process.env.API_KEY; if (!apiKey) { throw new Error('API key not provided'); } if (!limiter.name) { throw new Error('Function name not provided'); } if (limiter.verbose) { console.log(`[FlameShield] Checking quota for function: ${limiter.name}, max calls: ${limiter.maxCalls}, period: ${limiter.periodSeconds}s`); } const p = yield (0, remote_1.remotePost)({ functionName: limiter.name, qualifier: limiter.qualifier, maxCalls: limiter.maxCalls, periodSeconds: limiter.periodSeconds, version: version_1.VERSION // Use the hard-coded version from our provider }, apiKey, limiter.remoteUrl, { verbose: limiter.verbose }); if (limiter.verbose) { console.log(`[FlameShield] Quota check result: ${p ? 'exceeded' : 'within limits'}`); } return p; }); class ConfigurationRetrieverSingleton { constructor() { } static getInstance(app) { if (!ConfigurationRetrieverSingleton.instance) { ConfigurationRetrieverSingleton.instance = new configuration_retriever_1.ConfigurationRetriever(app); } return ConfigurationRetrieverSingleton.instance; } } const rateLimit = (struct) => __awaiter(void 0, void 0, void 0, function* () { // Default verbose to false if not provided const configuration = Object.assign(Object.assign({}, struct), { verbose: struct.verbose || false }); const functionName = configuration.name || process.env.FUNCTION_TARGET || process.env.K_SERVICE || process.env.FUNCTION_NAME; if (!functionName) { throw new Error('Function name not provided'); } configuration.name = functionName; if (configuration.verbose) { console.log(`[FlameShield] Processing rate limit for function: ${functionName}`); } yield ConfigurationRetrieverSingleton.getInstance(configuration.app).load(); const rateLimit = new rate_limiting_enabled_1.RateLimitingEnabled(functionName, ConfigurationRetrieverSingleton.getInstance(configuration.app), { verbose: configuration.verbose }); if (configuration.verbose) { console.log(`[FlameShield] Rate limiting enabled for ${functionName}: ${rateLimit.enabled}`); } if (!rateLimit.enabled) { if (configuration.verbose) { console.log(`[FlameShield] Rate limiting disabled, proceeding with function execution`); } return configuration.onSuccess(); } const updatedQuota = () => { return checkAndUpdateQuota(configuration); }; // Pass the verbose option to the RateLimiter constructor const limiter = new rate_limiter_1.RateLimiter(updatedQuota, { verbose: configuration.verbose }); if (configuration.verbose) { console.log(`[FlameShield] Checking and updating quota`); } const quotaExceeded = yield limiter.checkAndUpdateQuota(); if (!quotaExceeded) { if (configuration.verbose) { console.log(`[FlameShield] Quota not exceeded, proceeding with function execution`); } return configuration.onSuccess(); } else if (configuration.onFailure) { if (configuration.verbose) { console.log(`[FlameShield] Quota exceeded, executing failure handler`); } return configuration.onFailure(); } else { if (configuration.verbose) { console.log(`[FlameShield] Quota exceeded, throwing error`); } throw new Error('Rate limit exceeded'); } }); exports.rateLimit = rateLimit;