refactor: FileViewController를 presigned URL redirect 방식으로 전환
- 바이너리 스트리밍 프록시 → R2 presigned URL 302 redirect - 하드코딩 X-TENANT-ID: 287 → session 기반으로 수정 - 하드코딩 API 키 폴백 제거 - presigned URL 5분 캐시 적용 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,40 +2,48 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
|
||||
/**
|
||||
* R2 파일 프록시 (MNG 세션 인증으로 API 파일 스트리밍)
|
||||
* R2 파일 Presigned URL 리다이렉트
|
||||
*
|
||||
* MNG는 Blade(서버사이드)이므로 API의 /files/{id}/view를 직접 호출 시
|
||||
* sanctum 인증 문제가 발생. MNG 세션 인증으로 API를 프록시하여 파일 스트리밍.
|
||||
* API에서 R2 presigned URL을 발급받아 브라우저를 직접 R2로 리다이렉트.
|
||||
* presigned URL은 5분간 캐시하여 동일 이미지 반복 요청 시 API 호출 최소화.
|
||||
*/
|
||||
class FileViewController extends Controller
|
||||
{
|
||||
public function show(int $id)
|
||||
{
|
||||
$baseUrl = config('services.api.base_url', 'https://api.sam.kr');
|
||||
$apiKey = config('services.api.key') ?: '42Jfwc6EaRQ04GNRmLR5kzJp5UudSOzGGqjmdk1a';
|
||||
$token = session('api_access_token', '');
|
||||
$cacheKey = "file_presigned_url:{$id}";
|
||||
|
||||
$response = Http::baseUrl($baseUrl)
|
||||
->withoutVerifying()
|
||||
->withHeaders([
|
||||
'X-API-KEY' => $apiKey,
|
||||
'X-TENANT-ID' => 287, // TODO: session('selected_tenant_id', 1) 로 복원
|
||||
])
|
||||
->withToken($token)
|
||||
->timeout(15)
|
||||
->get("/api/v1/files/{$id}/view");
|
||||
$url = Cache::remember($cacheKey, now()->addMinutes(5), function () use ($id) {
|
||||
$baseUrl = config('services.api.base_url', 'https://api.sam.kr');
|
||||
$apiKey = config('services.api.key');
|
||||
$token = session('api_access_token', '');
|
||||
|
||||
if (! $response->successful()) {
|
||||
$response = Http::baseUrl($baseUrl)
|
||||
->withoutVerifying()
|
||||
->withHeaders([
|
||||
'X-API-KEY' => $apiKey,
|
||||
'X-TENANT-ID' => session('selected_tenant_id', 1),
|
||||
])
|
||||
->withToken($token)
|
||||
->timeout(10)
|
||||
->get("/api/v1/files/{$id}/presigned-url");
|
||||
|
||||
if (! $response->successful()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $response->json('data.url');
|
||||
});
|
||||
|
||||
if (! $url) {
|
||||
Cache::forget($cacheKey);
|
||||
abort(404);
|
||||
}
|
||||
|
||||
return response($response->body(), 200, [
|
||||
'Content-Type' => $response->header('Content-Type', 'image/png'),
|
||||
'Content-Disposition' => 'inline',
|
||||
'Cache-Control' => 'private, max-age=3600',
|
||||
]);
|
||||
return redirect($url);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user