diff --git a/packages/api/src/index.ts b/packages/api/src/index.ts index 9c9a08d0..020cb1ce 100644 --- a/packages/api/src/index.ts +++ b/packages/api/src/index.ts @@ -9,6 +9,7 @@ import cors from 'cors' import apiRouter from './routes' import { EigenExplorerApiError, handleAndReturnErrorResponse } from './schema/errors' import { startUserRequestsSync } from './utils/userRequestsSync' +import { requestsStore } from './utils/authCache' const PORT = process.env.PORT ? Number.parseInt(process.env.PORT) : 3002 @@ -23,6 +24,24 @@ app.use(express.json()) app.use(express.urlencoded({ extended: false })) app.use(cookieParser()) +// Route cost increment +app.use((req, res, next) => { + res.on('finish', () => { + try { + if (res.statusCode >= 200 && res.statusCode < 300) { + const apiToken = req.header('X-API-Token') + if (apiToken) { + const key = `apiToken:${apiToken}:newRequests` + const currentCalls: number = requestsStore.get(key) || 0 + const cost = req.cost || 1 + requestsStore.set(key, currentCalls + cost) + } + } + } catch {} + }) + next() +}) + // Routes app.use('/', apiRouter) diff --git a/packages/api/src/utils/authMiddleware.ts b/packages/api/src/utils/authMiddleware.ts index 989a505d..475854d7 100644 --- a/packages/api/src/utils/authMiddleware.ts +++ b/packages/api/src/utils/authMiddleware.ts @@ -151,27 +151,6 @@ export const rateLimiter = (req: Request, res: Response, next: NextFunction) => // Apply rate limiting const limiter = rateLimiters[accessLevel] - - // Increment `requestsStore` for successful requests - const originalEnd = res.end - - // biome-ignore lint/suspicious/noExplicitAny: - res.end = function (chunk?: any, encoding?: any, cb?: any) { - try { - if (res.statusCode >= 200 && res.statusCode < 300) { - const apiToken = req.header('X-API-Token') - if (apiToken) { - const key = `apiToken:${apiToken}:newRequests` - const currentCalls: number = requestsStore.get(key) || 0 - requestsStore.set(key, currentCalls + 1) - } - } - } catch {} - - res.end = originalEnd - return originalEnd.call(this, chunk, encoding, cb) - } - return limiter(req, res, next) } diff --git a/packages/api/src/utils/request.ts b/packages/api/src/utils/request.ts index aed37e71..bbfc27af 100644 --- a/packages/api/src/utils/request.ts +++ b/packages/api/src/utils/request.ts @@ -4,6 +4,7 @@ declare global { namespace Express { interface Request { accessLevel?: number + cost?: number } } } diff --git a/packages/api/src/utils/routeCost.ts b/packages/api/src/utils/routeCost.ts new file mode 100644 index 00000000..1734a19f --- /dev/null +++ b/packages/api/src/utils/routeCost.ts @@ -0,0 +1,15 @@ +import type { NextFunction, Request, Response } from 'express' + +/** + * Middleware function to be used when defining API routes and pointing them to their internal functions + * If not set, cost calculator after route completion will consider cost as 1 + * + * @param cost + * @returns + */ +export function setRouteCost(cost: number) { + return (req: Request, _res: Response, next: NextFunction) => { + req.cost = cost + next() + } +}