mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 10:11:13 -05:00
Improve form validation and image handling for entities
Refactor validation logic for 'founded_year' in multiple form components, enhance image cleanup in `EntityMultiImageUploader`, update `useEntityVersions` to prevent race conditions, improve error handling for recent searches in `useSearch`, refine rate limiting logic in `detect-location` Supabase function, and update CORS configuration for `upload-image` Supabase function. Replit-Commit-Author: Agent Replit-Commit-Session-Id: b9af4867-23a7-43cc-baeb-4a97f66b4150 Replit-Commit-Checkpoint-Type: intermediate_checkpoint
This commit is contained in:
@@ -18,11 +18,22 @@ const MAX_REQUESTS = 10; // 10 requests per minute per IP
|
||||
const MAX_MAP_SIZE = 10000; // Maximum number of IPs to track
|
||||
|
||||
function cleanupExpiredEntries() {
|
||||
const now = Date.now();
|
||||
for (const [ip, data] of rateLimitMap.entries()) {
|
||||
if (now > data.resetAt) {
|
||||
rateLimitMap.delete(ip);
|
||||
try {
|
||||
const now = Date.now();
|
||||
let deletedCount = 0;
|
||||
|
||||
for (const [ip, data] of rateLimitMap.entries()) {
|
||||
if (now > data.resetAt) {
|
||||
rateLimitMap.delete(ip);
|
||||
deletedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (deletedCount > 0) {
|
||||
console.log(`Cleaned up ${deletedCount} expired rate limit entries`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error during cleanup:', error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,16 +46,17 @@ function checkRateLimit(ip: string): { allowed: boolean; retryAfter?: number } {
|
||||
if (rateLimitMap.size >= MAX_MAP_SIZE) {
|
||||
cleanupExpiredEntries();
|
||||
|
||||
// If still too large after cleanup, clear oldest entries
|
||||
// If still too large after cleanup, remove entries based on LRU (oldest resetAt)
|
||||
if (rateLimitMap.size >= MAX_MAP_SIZE) {
|
||||
const toDelete = Math.floor(MAX_MAP_SIZE * 0.2); // Remove 20% of entries
|
||||
let deleted = 0;
|
||||
for (const key of rateLimitMap.keys()) {
|
||||
if (deleted >= toDelete) break;
|
||||
rateLimitMap.delete(key);
|
||||
deleted++;
|
||||
const toDelete = Math.floor(MAX_MAP_SIZE * 0.3); // Remove 30% of entries
|
||||
const sortedEntries = Array.from(rateLimitMap.entries())
|
||||
.sort((a, b) => a[1].resetAt - b[1].resetAt);
|
||||
|
||||
for (let i = 0; i < toDelete && i < sortedEntries.length; i++) {
|
||||
rateLimitMap.delete(sortedEntries[i][0]);
|
||||
}
|
||||
console.warn(`Rate limit map reached size limit. Cleared ${deleted} entries.`);
|
||||
|
||||
console.warn(`Rate limit map reached ${MAX_MAP_SIZE} entries. Cleared ${toDelete} oldest entries.`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +75,8 @@ function checkRateLimit(ip: string): { allowed: boolean; retryAfter?: number } {
|
||||
}
|
||||
|
||||
// Clean up old entries periodically to prevent memory leak
|
||||
setInterval(cleanupExpiredEntries, RATE_LIMIT_WINDOW);
|
||||
// Run cleanup more frequently to catch expired entries sooner
|
||||
setInterval(cleanupExpiredEntries, Math.min(RATE_LIMIT_WINDOW / 2, 30000)); // Every 30 seconds or half the window
|
||||
|
||||
serve(async (req) => {
|
||||
// Handle CORS preflight requests
|
||||
|
||||
Reference in New Issue
Block a user