fix: increase rate limit and add detailed logging to diagnose broken thumbnails

This commit is contained in:
ralksta
2026-03-07 09:42:33 +01:00
parent 68e442fff5
commit faab17f9cd
2 changed files with 7 additions and 11 deletions

View File

@@ -31,16 +31,8 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{
if (!success) { if (!success) {
const retryAfter = Math.ceil((resetAt - Date.now()) / 1000); const retryAfter = Math.ceil((resetAt - Date.now()) / 1000);
return NextResponse.json( console.warn(`[Image API] ⚠️ Rate limit exceeded for IP: ${ip}. Retry after ${retryAfter}s`);
{ error: 'Too many requests' }, return NextResponse.json({ error: 'Too many requests' }, { status: 429 });
{
status: 429,
headers: {
'Retry-After': String(retryAfter),
'X-RateLimit-Remaining': '0',
},
},
);
} }
const { id: token } = await params; const { id: token } = await params;
@@ -48,6 +40,7 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{
// Decode the opaque token back to an Immich asset ID // Decode the opaque token back to an Immich asset ID
const assetId = decodeAssetId(token); const assetId = decodeAssetId(token);
if (!assetId) { if (!assetId) {
console.error(`[Image API] ❌ Invalid token: ${token.substring(0, 10)}...`);
return NextResponse.json({ error: 'Invalid token' }, { status: 400 }); return NextResponse.json({ error: 'Invalid token' }, { status: 400 });
} }
@@ -67,9 +60,12 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{
const result = await immich.streamAsset(assetId, size); const result = await immich.streamAsset(assetId, size);
if (!result) { if (!result) {
console.error(`[Image API] ❌ Asset not found in Immich: ${assetId} (Size: ${size})`);
return NextResponse.json({ error: 'Asset not found' }, { status: 404 }); return NextResponse.json({ error: 'Asset not found' }, { status: 404 });
} }
console.log(`[Image API] ✅ Serving ${assetId} (${size}) - Type: ${result.contentType}`);
const headers: Record<string, string> = { const headers: Record<string, string> = {
'Content-Type': result.contentType, 'Content-Type': result.contentType,
// Images are immutable once uploaded to Immich — cache aggressively // Images are immutable once uploaded to Immich — cache aggressively

View File

@@ -25,7 +25,7 @@ const envSchema = z.object({
CACHE_TTL: z.coerce.number().int().min(0).default(300), CACHE_TTL: z.coerce.number().int().min(0).default(300),
/** Rate limit: max requests per minute per IP */ /** Rate limit: max requests per minute per IP */
RATE_LIMIT_RPM: z.coerce.number().int().min(1).default(120), RATE_LIMIT_RPM: z.coerce.number().int().min(1).default(600),
/** /**
* Secret used for signing auth cookies and encrypting asset tokens. * Secret used for signing auth cookies and encrypting asset tokens.