From 5f653a4c9f7c76d461ee4377fb4e025771cff872 Mon Sep 17 00:00:00 2001
From: yyamashita <yyamashita@hetzner.yyamashita.com>
Date: Wed, 17 Jun 2026 22:27:47 +0900
Subject: Add image proxy endpoint to avoid mixed content issues

Serve external event images through /api/image?url=<encoded> so HTTP
image URLs from venue sites are fetched server-side and delivered over
HTTPS. Validates Content-Type is image/*, blocks private IPs (SSRF),
and caches responses in memory (24h TTL, 200-entry LRU).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---
 app/routes/events.$id.tsx | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'app/routes/events.$id.tsx')

diff --git a/app/routes/events.$id.tsx b/app/routes/events.$id.tsx
index 87c5e2d..87836ed 100644
--- a/app/routes/events.$id.tsx
+++ b/app/routes/events.$id.tsx
@@ -1,6 +1,7 @@
 import { useLoaderData, Link } from "react-router";
 import type { Route } from "./+types/events.$id";
 import { getEvent } from "~/lib/db.server";
+import { proxyImageUrl } from "~/lib/image-proxy";
 
 export async function loader({ params }: Route.LoaderArgs) {
   const id = parseInt(params.id, 10);
@@ -83,7 +84,7 @@ export default function EventDetail() {
         <div className="mt-6">
           {event.image_url && (
             <img
-              src={event.image_url}
+              src={proxyImageUrl(event.image_url)!}
               alt={event.title}
               className="w-full object-contain rounded-xl mb-6"
             />
-- 
cgit v1.2.3

