From f19d5de52b97cd93c43a9fc54baea82233d77202 Mon Sep 17 00:00:00 2001 From: Apple Date: Tue, 2 Dec 2025 08:50:13 -0800 Subject: [PATCH] fix: Add HEAD method support and fix proxy URL in Next.js assets route - Add HEAD method handler in Next.js route - Fix proxy URL to use correct city-service endpoint - Handle HEAD requests properly (return headers only) - This should fix 405 errors when browser checks image availability --- .../web/src/app/api/assets/[...path]/route.ts | 46 +++++++++++++++---- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/apps/web/src/app/api/assets/[...path]/route.ts b/apps/web/src/app/api/assets/[...path]/route.ts index 257e0b3e..36073953 100644 --- a/apps/web/src/app/api/assets/[...path]/route.ts +++ b/apps/web/src/app/api/assets/[...path]/route.ts @@ -14,6 +14,20 @@ const ASSETS_BUCKET = process.env.ASSETS_BUCKET || 'daarion-assets'; export async function GET( request: NextRequest, { params }: { params: Promise<{ path: string[] }> } +) { + return handleAssetRequest(request, params); +} + +export async function HEAD( + request: NextRequest, + { params }: { params: Promise<{ path: string[] }> } +) { + return handleAssetRequest(request, params); +} + +async function handleAssetRequest( + request: NextRequest, + { params }: { params: Promise<{ path: string[] }> } ) { try { const { path } = await params; @@ -24,15 +38,18 @@ export async function GET( // Should proxy to: http://minio:9000/daarion-assets/microdao/logo/2025/12/02/abc123.png const minioUrl = `${MINIO_ENDPOINT}/${ASSETS_BUCKET}/${objectPath}`; - // For Docker network, use service name - // For external access, we need to proxy through city-service or use internal network - const proxyUrl = process.env.INTERNAL_API_URL - ? `${process.env.INTERNAL_API_URL.replace('/city', '')}/assets/proxy/${objectPath}` - : minioUrl; + // Proxy through city-service + // INTERNAL_API_URL is like http://daarion-city-service:7001 + // We need: http://daarion-city-service:7001/city/assets/proxy/... + const cityServiceUrl = process.env.INTERNAL_API_URL || 'http://daarion-city-service:7001'; + const proxyUrl = `${cityServiceUrl}/city/assets/proxy/${objectPath}`; - // Try to fetch from MinIO + // Use the same HTTP method as the incoming request (GET or HEAD) + const method = request.method as 'GET' | 'HEAD'; + + // Try to fetch from city-service proxy const response = await fetch(proxyUrl, { - method: 'GET', + method: method, headers: { 'Accept': request.headers.get('Accept') || '*/*', }, @@ -46,7 +63,20 @@ export async function GET( const contentType = response.headers.get('Content-Type') || 'application/octet-stream'; const contentLength = response.headers.get('Content-Length'); - // Stream the response + // For HEAD requests, return headers only + if (method === 'HEAD') { + return new NextResponse(null, { + status: 200, + headers: { + 'Content-Type': contentType, + 'Content-Length': contentLength || '0', + 'Cache-Control': 'public, max-age=86400, immutable', + 'Access-Control-Allow-Origin': '*', + }, + }); + } + + // For GET requests, return file data const blob = await response.blob(); const buffer = await blob.arrayBuffer();