From 8c25cb5320d98e8dc3e7034434e4900f1f3f7d18 Mon Sep 17 00:00:00 2001 From: lukmay Date: Wed, 2 Jul 2025 18:27:43 +0200 Subject: [PATCH 1/2] fix thumbnail URL generation logic to handle path style and virtual-hosted style URLs correctly --- apps/web/app/api/thumbnail/route.ts | 52 +++++++++++++++-------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/apps/web/app/api/thumbnail/route.ts b/apps/web/app/api/thumbnail/route.ts index 1dbfdc45d..1e853722f 100644 --- a/apps/web/app/api/thumbnail/route.ts +++ b/apps/web/app/api/thumbnail/route.ts @@ -60,43 +60,45 @@ export async function GET(request: NextRequest) { const { video } = result; const prefix = `${userId}/${videoId}/`; - + const screenshotPath = `${prefix}screenshot/screen-capture.jpg`; let thumbnailUrl: string; - if (!result.bucket || video.awsBucket === serverEnv().CAP_AWS_BUCKET) { - thumbnailUrl = `${S3_BUCKET_URL}/${prefix}screenshot/screen-capture.jpg`; + const usePathStyle = serverEnv().S3_PATH_STYLE; + const customBucketUrl = serverEnv().CAP_AWS_BUCKET_URL; + const endpoint = serverEnv().CAP_AWS_ENDPOINT; + + // Handle path-style URLs + if (usePathStyle && endpoint && video.awsBucket) { + thumbnailUrl = `${endpoint}/${video.awsBucket}/${screenshotPath}`; return new Response(JSON.stringify({ screen: thumbnailUrl }), { status: 200, headers: getHeaders(origin), }); } - const bucketProvider = await createBucketProvider(result.bucket); - - try { - const listResponse = await bucketProvider.listObjects({ - prefix: prefix, + // Handle virtual-hosted/subdomain style URLs + if (!usePathStyle && customBucketUrl) { + thumbnailUrl = `${customBucketUrl}/${screenshotPath}`; + return new Response(JSON.stringify({ screen: thumbnailUrl }), { + status: 200, + headers: getHeaders(origin), }); - const contents = listResponse.Contents || []; + } - const thumbnailKey = contents.find((item: any) => - item.Key?.endsWith("screen-capture.jpg") - )?.Key; - if (!thumbnailKey) { - return new Response( - JSON.stringify({ - error: true, - message: "No thumbnail found for this video", - }), - { - status: 404, - headers: getHeaders(origin), - } - ); - } + // Fallback if no custom URL/endpoint is configured + if (!result.bucket || video.awsBucket === serverEnv().CAP_AWS_BUCKET) { + thumbnailUrl = `${S3_BUCKET_URL}/${screenshotPath}`; + return new Response(JSON.stringify({ screen: thumbnailUrl }), { + status: 200, + headers: getHeaders(origin), + }); + } - thumbnailUrl = await bucketProvider.getSignedObjectUrl(thumbnailKey); + // Fallback for other custom S3 setups that require pre-signed URLs + const bucketProvider = await createBucketProvider(result.bucket); + try { + thumbnailUrl = await bucketProvider.getSignedObjectUrl(screenshotPath); } catch (error) { return new Response( JSON.stringify({ From 8ed36ed4c4860fb89c14592786ee49a0a6996ddf Mon Sep 17 00:00:00 2001 From: lukmay Date: Wed, 2 Jul 2025 18:28:03 +0200 Subject: [PATCH 2/2] fix response status codes for non-existent videos to return 404 instead of 401 --- apps/web/app/api/thumbnail/route.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/web/app/api/thumbnail/route.ts b/apps/web/app/api/thumbnail/route.ts index 1e853722f..2f6e691fc 100644 --- a/apps/web/app/api/thumbnail/route.ts +++ b/apps/web/app/api/thumbnail/route.ts @@ -41,7 +41,7 @@ export async function GET(request: NextRequest) { return new Response( JSON.stringify({ error: true, message: "Video does not exist" }), { - status: 401, + status: 404, headers: getHeaders(origin), } ); @@ -52,7 +52,7 @@ export async function GET(request: NextRequest) { return new Response( JSON.stringify({ error: true, message: "Video not found" }), { - status: 401, + status: 404, headers: getHeaders(origin), } );