/** * Proxy endpoint para obtener snapshots de eventos de Frigate * GET /api/frigate/events/:eventId/snapshot */ export default defineEventHandler(async (event) => { // Verificar autenticación via headers de Authentik const headers = getRequestHeaders(event) const username = headers['x-authentik-username'] if (!username) { throw createError({ statusCode: 401, message: 'No autenticado' }) } const eventId = getRouterParam(event, 'eventId') if (!eventId) { throw createError({ statusCode: 400, message: 'Se requiere eventId' }) } // URL interna de Frigate const FRIGATE_URL = process.env.FRIGATE_URL || 'http://192.168.87.29:5000' try { const response = await fetch( `${FRIGATE_URL}/api/events/${eventId}/snapshot.jpg`, { method: 'GET', headers: { 'Accept': 'image/jpeg' } } ) if (!response.ok) { throw createError({ statusCode: response.status, message: `Error al obtener snapshot: ${response.statusText}` }) } // Configurar headers de respuesta setResponseHeader(event, 'Content-Type', 'image/jpeg') const contentLength = response.headers.get('content-length') if (contentLength) { setResponseHeader(event, 'Content-Length', contentLength) } // Cache por 5 minutos (los snapshots no cambian) setResponseHeader(event, 'Cache-Control', 'public, max-age=300') // Retornar el stream de la imagen return response.body } catch (error: unknown) { console.error('[Frigate Snapshot Proxy] Error:', error) if ((error as any).statusCode) { throw error } throw createError({ statusCode: 500, message: (error as Error)?.message || 'Error al obtener snapshot' }) } })