From 765b3588a377c8a163b65564f34819a5459faca0 Mon Sep 17 00:00:00 2001 From: asepharyana Date: Sun, 30 Aug 2026 17:54:41 +0700 Subject: [PATCH] fix(files): serve /f/:public_id as CORS-enabled 200 stream instead of 302 redirect to Telegram CDN Fixes browser CORS error when frontend fetches audio via Web Audio API (decodeAudio): the 302 redirected to api.telegram.org which lacks Access-Control-Allow-Origin, blocking fetch/XHR. Now the file bytes are proxied server-side with CORS headers + proper Content-Type, so the browser stays same-origin. Also adds CORS to chunked/archive streams. --- .../http/controllers/file-controller.ts | 72 ++++++++++++++++--- 1 file changed, 64 insertions(+), 8 deletions(-) diff --git a/src/interfaces/http/controllers/file-controller.ts b/src/interfaces/http/controllers/file-controller.ts index 972c15a..0e7f830 100644 --- a/src/interfaces/http/controllers/file-controller.ts +++ b/src/interfaces/http/controllers/file-controller.ts @@ -106,7 +106,12 @@ export const handleFileRedirect = async (req: RequestWithParams): Promise = { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Expose-Headers': 'Content-Disposition, Content-Length, Accept-Ranges', + 'Access-Control-Allow-Methods': 'GET, HEAD, OPTIONS', + 'Access-Control-Allow-Headers': 'Range, Content-Type', + Vary: 'Origin', + }; + + try { + const upstream = await fetch(telegramUrl); + if (!upstream.ok) { + logger.error('Telegram file download failed', { + publicId, + status: upstream.status, + }); + return Response.json( + { error: 'Upstream download failed' }, + { + status: upstream.status === 404 ? 404 : 502, + headers: corsHeaders, + }, + ); + } + + const upstreamHeaders = new Headers(upstream.headers); + const contentType = + file.mimeType || upstreamHeaders.get('content-type') || 'application/octet-stream'; + const headers = { + 'Content-Type': contentType, + 'Content-Disposition': `inline; filename="${sanitizeFilenameHeader(file.fileName)}"`, + 'Content-Length': String(file.sizeBytes ?? 0), + 'Cache-Control': 'public, max-age=300', + ...corsHeaders, + }; + + // Stream the Telegram CDN body back to the client (no cross-origin hop + // in the browser → no CORS block for fetch/XHR audio playback). + return new Response(upstream.body, { + status: 200, + headers, + }); + } catch (error: unknown) { + logger.error('Telegram file proxy error', { + publicId, + error: getErrorMessage(error), + }); + return Response.json( + { error: 'Upstream download failed' }, + { + status: 502, + headers: corsHeaders, + }, + ); + } } catch (error: unknown) { logger.error('File redirect error', { publicId, error: getErrorMessage(error) }); return fail(500, 'Server error');