vk98's picture
Initial backend deployment - Hono proxy + ColPali embedding API
5dfbe50
import { Context, Next } from 'hono';
import { config } from '../config';
interface RateLimitStore {
[key: string]: {
count: number;
resetTime: number;
};
}
const store: RateLimitStore = {};
// Simple in-memory rate limiter
export const rateLimitMiddleware = async (c: Context, next: Next) => {
const ip = c.req.header('x-forwarded-for') || c.req.header('x-real-ip') || 'unknown';
const now = Date.now();
const windowStart = now - config.rateLimit.windowMs;
// Clean up old entries
Object.keys(store).forEach(key => {
if (store[key].resetTime < windowStart) {
delete store[key];
}
});
// Check rate limit
if (!store[ip]) {
store[ip] = { count: 1, resetTime: now + config.rateLimit.windowMs };
} else if (store[ip].resetTime < now) {
store[ip] = { count: 1, resetTime: now + config.rateLimit.windowMs };
} else {
store[ip].count++;
}
if (store[ip].count > config.rateLimit.max) {
return c.json(
{ error: 'Too many requests', retryAfter: Math.ceil((store[ip].resetTime - now) / 1000) },
429,
{
'Retry-After': Math.ceil((store[ip].resetTime - now) / 1000).toString(),
'X-RateLimit-Limit': config.rateLimit.max.toString(),
'X-RateLimit-Remaining': '0',
'X-RateLimit-Reset': new Date(store[ip].resetTime).toISOString(),
}
);
}
// Add rate limit headers
c.header('X-RateLimit-Limit', config.rateLimit.max.toString());
c.header('X-RateLimit-Remaining', (config.rateLimit.max - store[ip].count).toString());
c.header('X-RateLimit-Reset', new Date(store[ip].resetTime).toISOString());
await next();
};