From ef591074c7072f383376af2d0700f66a10af5c54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B6=8C=ED=98=81=EC=84=B1?= Date: Fri, 13 Mar 2026 10:13:50 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20[storage]=20R2=20=ED=85=8C=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=ED=8C=8C=EC=9D=BC=20=ED=94=84=EB=A1=9D=EC=8B=9C=20?= =?UTF-8?q?=EB=9D=BC=EC=9A=B0=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - /storage/tenants/{path} 라우트 추가 - R2에서 스트리밍 방식으로 파일 제공 - 인증 불필요, Cache-Control 1일 Co-Authored-By: Claude Opus 4.6 --- routes/web.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/routes/web.php b/routes/web.php index bbf6039..d72b935 100644 --- a/routes/web.php +++ b/routes/web.php @@ -38,6 +38,26 @@ ]); })->where('path', '.*'); +// R2 테넌트 파일 프록시 (문서 템플릿 이미지 등, 인증 불필요, 캐시 1일) +Route::get('/storage/tenants/{path}', function (string $path) { + if (! Storage::disk('r2')->exists($path)) { + abort(404); + } + + $mime = Storage::disk('r2')->mimeType($path); + $stream = Storage::disk('r2')->readStream($path); + + return response()->stream(function () use ($stream) { + fpassthru($stream); + if (is_resource($stream)) { + fclose($stream); + } + }, 200, [ + 'Content-Type' => $mime, + 'Cache-Control' => 'public, max-age=86400', + ]); +})->where('path', '.*'); + // Swagger 설정 Route::get('/docs/api-docs.json', function () { return response()->file(storage_path('api-docs/api-docs.json'));