diff --git a/__tests__/lib/directus.test.ts b/__tests__/lib/directus.test.ts index 7ee128a..4af6b65 100644 --- a/__tests__/lib/directus.test.ts +++ b/__tests__/lib/directus.test.ts @@ -60,10 +60,10 @@ describe('getArticleBySlug', () => { }) describe('getAssetUrl', () => { - it('constructs a Directus asset URL from a file UUID', async () => { + it('constructs a proxied asset URL from a file UUID', async () => { const { getAssetUrl } = await import('@/lib/directus') const url = getAssetUrl('abc-123-uuid') - expect(url).toBe('https://cms.achmad.dev/assets/abc-123-uuid') + expect(url).toBe('/api/image/abc-123-uuid') }) it('appends width and quality query params', async () => { @@ -71,5 +71,6 @@ describe('getAssetUrl', () => { const url = getAssetUrl('abc-123-uuid', { width: 800, quality: 80 }) expect(url).toContain('width=800') expect(url).toContain('quality=80') + expect(url).toContain('/api/image/') }) }) diff --git a/app/api/image/[id]/route.ts b/app/api/image/[id]/route.ts new file mode 100644 index 0000000..6a8ba95 --- /dev/null +++ b/app/api/image/[id]/route.ts @@ -0,0 +1,35 @@ +import { NextRequest, NextResponse } from 'next/server' + +export async function GET( + req: NextRequest, + { params }: { params: Promise<{ id: string }> }, +) { + const { id } = await params + const { searchParams } = new URL(req.url) + const width = searchParams.get('width') || '800' + const quality = searchParams.get('quality') || '80' + + const directusUrl = process.env.DIRECTUS_URL! + const token = process.env.DIRECTUS_TOKEN! + + try { + const res = await fetch( + `${directusUrl}/assets/${id}?width=${width}&quality=${quality}`, + { + headers: { Authorization: `Bearer ${token}` }, + }, + ) + + if (!res.ok) { + return NextResponse.json({ error: 'Image not found' }, { status: 404 }) + } + + const headers = new Headers() + headers.set('Content-Type', res.headers.get('Content-Type') || 'image/jpeg') + headers.set('Cache-Control', 'public, max-age=31536000, immutable') + + return new NextResponse(res.body, { status: 200, headers }) + } catch { + return NextResponse.json({ error: 'Failed to fetch image' }, { status: 502 }) + } +} diff --git a/lib/directus.ts b/lib/directus.ts index 73af50d..b6e607e 100644 --- a/lib/directus.ts +++ b/lib/directus.ts @@ -160,9 +160,9 @@ export function getAssetUrl( fileId: string, params?: { width?: number; height?: number; quality?: number }, ): string { - const url = new URL(`/assets/${fileId}`, process.env.DIRECTUS_URL!) + const url = new URL(`/api/image/${fileId}`, 'http://localhost') if (params?.width) url.searchParams.set('width', String(params.width)) if (params?.height) url.searchParams.set('height', String(params.height)) if (params?.quality) url.searchParams.set('quality', String(params.quality)) - return url.toString() + return url.pathname + url.search }