From 50d31ef8949f0982969ca325eee30e44bb3ba43a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yusuf=20=C4=B0pek?= Date: Tue, 14 Apr 2026 13:56:27 +0300 Subject: [PATCH] feat(download): add estimation of egress bytes by fetching Content-Length via HEAD request --- app/api/versions/[versionId]/download/route.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/app/api/versions/[versionId]/download/route.ts b/app/api/versions/[versionId]/download/route.ts index 35b65f0..ec3cd1e 100644 --- a/app/api/versions/[versionId]/download/route.ts +++ b/app/api/versions/[versionId]/download/route.ts @@ -327,6 +327,19 @@ export async function GET(request: NextRequest, { params }: RouteParams) { return withCacheControl(response, 'private, no-store'); } + // Fetch Content-Length via HEAD so we can record egress bytes without proxying the body. + let estimatedBytes = BigInt(0); + try { + const headRes = await fetchWithTimeout(source.url, { method: 'HEAD', cache: 'no-store' }); + const cl = headRes.headers.get('content-length'); + if (cl && /^\d+$/.test(cl.trim())) { + const parsed = BigInt(cl.trim()); + if (parsed > BigInt(0)) estimatedBytes = parsed; + } + } catch { + // Best-effort — leave estimatedBytes as 0 if HEAD fails. + } + try { await db.downloadEgressEvent.create({ data: { @@ -338,7 +351,7 @@ export async function GET(request: NextRequest, { params }: RouteParams) { downloaderUserId: session?.user?.id ?? null, source: source.sourceType === 'original' ? DownloadEgressSource.ORIGINAL : DownloadEgressSource.COMPRESSED, quality: source.quality, - estimatedBytes: BigInt(0), + estimatedBytes, }, }); } catch (egressError) {