diff --git a/app/[locale]/errors/api/relay/route.ts b/app/[locale]/errors/api/relay/route.ts index 44664c754..63163e526 100644 --- a/app/[locale]/errors/api/relay/route.ts +++ b/app/[locale]/errors/api/relay/route.ts @@ -1,4 +1,5 @@ import { NextResponse } from 'next/server'; +import https from 'https'; const ALLOWED_HOSTS = ['glitchtip.infra.mintel.me', 'errors.infra.mintel.me']; @@ -36,21 +37,45 @@ export async function POST(req: Request) { const sentryIngestUrl = `https://${host}/api/${projectId}/envelope/`; const payloadToForward = items.join('\n'); - const response = await fetch(sentryIngestUrl, { - method: 'POST', - body: payloadToForward, - headers: { - 'Content-Type': 'application/x-sentry-envelope', - }, + return new Promise((resolve) => { + const req = https.request( + sentryIngestUrl, + { + method: 'POST', + headers: { + 'Content-Type': 'application/x-sentry-envelope', + }, + // Bypass self-signed cert error since glitchtip.infra.mintel.me uses an internal CA + // that the Next.js docker container doesn't trust by default. + rejectUnauthorized: false, + }, + (res) => { + res.on('data', () => { + // Consume data to free up memory + }); + res.on('end', () => { + if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) { + resolve(NextResponse.json({ success: true })); + } else { + resolve( + NextResponse.json( + { error: `Relay rejected (${res.statusCode})` }, + { status: res.statusCode || 500 } + ) + ); + } + }); + } + ); + + req.on('error', (err) => { + console.error('[Sentry Tunnel] https.request failed', err); + resolve(NextResponse.json({ error: 'Relay failed' }, { status: 500 })); + }); + + req.write(payloadToForward); + req.end(); }); - - if (!response.ok) { - const errorText = await response.text(); - console.error(`[Sentry Tunnel] Relay rejected (${response.status}):`, errorText); - return NextResponse.json({ error: 'Sentry rejection' }, { status: response.status }); - } - - return NextResponse.json({ success: true }); } catch (e) { console.error("[Sentry Tunnel] Failed to parse or relay body", e); return NextResponse.json({ error: 'Relay failed' }, { status: 500 });