From 3a45f4850363617c69a8cbe6e974a23f1e7c4d15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=B4=EA=B3=A4?= Date: Sat, 21 Mar 2026 14:51:08 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20[=EB=AC=B8=EC=84=9C=EC=96=91=EC=8B=9D]?= =?UTF-8?q?=20=EB=AF=B8=EB=A6=AC=EB=B3=B4=EA=B8=B0=20=EC=9D=B4=EB=AF=B8?= =?UTF-8?q?=EC=A7=80=20MNG=20API=20=ED=94=84=EB=A1=9D=EC=8B=9C=20=EA=B2=BD?= =?UTF-8?q?=EC=9C=A0=EB=A1=9C=20=EC=88=98=EC=A0=95=20(=EB=B8=8C=EB=9D=BC?= =?UTF-8?q?=EC=9A=B0=EC=A0=80=E2=86=92MNG=E2=86=92API=E2=86=92R2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Admin/DocumentTemplateApiController.php | 35 +++++++++++++++++++ .../partials/preview-modal.blade.php | 15 +++----- routes/api.php | 1 + 3 files changed, 41 insertions(+), 10 deletions(-) diff --git a/app/Http/Controllers/Api/Admin/DocumentTemplateApiController.php b/app/Http/Controllers/Api/Admin/DocumentTemplateApiController.php index 7b8eff1e..2042710a 100644 --- a/app/Http/Controllers/Api/Admin/DocumentTemplateApiController.php +++ b/app/Http/Controllers/Api/Admin/DocumentTemplateApiController.php @@ -927,4 +927,39 @@ private function checkLinkedItemDuplicates(?string $category, array $newItemIds, 'errors' => ['linked_items' => $messages], ], 422); } + + /** + * R2 image_path → presigned URL 프록시 (미리보기용) + */ + public function presignedUrlByPath(Request $request): JsonResponse + { + $path = $request->input('path'); + if (empty($path)) { + return response()->json(['url' => null], 400); + } + + $baseUrl = config('services.api.base_url', 'https://api.sam.kr'); + $internalUrl = config('services.api.internal_url'); + $apiKey = config('services.api.key'); + + $headers = [ + 'X-API-KEY' => $apiKey, + 'X-TENANT-ID' => session('selected_tenant_id', 1), + ]; + + if ($internalUrl) { + $headers['Host'] = parse_url($baseUrl, PHP_URL_HOST) ?: 'api.sam.kr'; + $baseUrl = $internalUrl; + } + + $response = Http::baseUrl($baseUrl) + ->withoutVerifying() + ->withHeaders($headers) + ->timeout(10) + ->post('/api/v1/files/presigned-url-by-path', ['path' => $path]); + + return response()->json([ + 'url' => $response->successful() ? $response->json('data.url') : null, + ]); + } } diff --git a/resources/views/document-templates/partials/preview-modal.blade.php b/resources/views/document-templates/partials/preview-modal.blade.php index b2727b00..592f43e6 100644 --- a/resources/views/document-templates/partials/preview-modal.blade.php +++ b/resources/views/document-templates/partials/preview-modal.blade.php @@ -35,27 +35,22 @@ function closePreviewModal() { if (e.key === 'Escape') closePreviewModal(); }); - // 이미지 URL 헬퍼 (file_id 기반 R2 프록시 + image_path R2 presigned URL) + // 이미지 URL 헬퍼 (file_id 기반 R2 프록시 + image_path presigned URL) function _previewImageUrl(section) { if (section.image_url) return section.image_url; if (section.file_id) return '/files/' + section.file_id + '/view'; if (!section.image_path) return ''; if (section.image_path.startsWith('http')) return section.image_path; - // R2 상대경로 — presigned URL 요청 (동기) + // R2 상대경로 — MNG API 경유 presigned URL 요청 (동기) try { const xhr = new XMLHttpRequest(); - xhr.open('POST', '{{ config("services.api.internal_url") ?: config("services.api.base_url") }}/api/v1/files/presigned-url-by-path', false); + xhr.open('POST', '/api/admin/document-templates/presigned-url-by-path', false); xhr.setRequestHeader('Content-Type', 'application/json'); - xhr.setRequestHeader('X-API-KEY', '{{ config("services.api.key") }}'); - xhr.setRequestHeader('X-TENANT-ID', '{{ session("selected_tenant_id", 1) }}'); - @if(config('services.api.internal_url')) - xhr.setRequestHeader('Host', '{{ parse_url(config("services.api.base_url"), PHP_URL_HOST) }}'); - @endif + xhr.setRequestHeader('X-CSRF-TOKEN', document.querySelector('meta[name="csrf-token"]')?.content || ''); xhr.send(JSON.stringify({ path: section.image_path })); if (xhr.status === 200) { const result = JSON.parse(xhr.responseText); - const url = result.data?.url; - if (url) { section.image_url = url; return url; } + if (result.url) { section.image_url = result.url; return result.url; } } } catch (e) { console.warn('Preview image URL fetch failed:', e); } return ''; diff --git a/routes/api.php b/routes/api.php index cfa83364..9c208df4 100644 --- a/routes/api.php +++ b/routes/api.php @@ -894,6 +894,7 @@ Route::post('/{id}/toggle-active', [DocumentTemplateApiController::class, 'toggleActive'])->name('toggle-active'); Route::post('/{id}/duplicate', [DocumentTemplateApiController::class, 'duplicate'])->name('duplicate'); Route::post('/upload-image', [DocumentTemplateApiController::class, 'uploadImage'])->name('upload-image'); + Route::post('/presigned-url-by-path', [DocumentTemplateApiController::class, 'presignedUrlByPath'])->name('presigned-url-by-path'); }); /*