route.ts63 lines · main
1import { IS_PLATFORM } from 'common'
2import { NextResponse } from 'next/server'
3
4import { InternalServerError } from '@/lib/api/apiHelpers'
5import { getBannerIncidents } from '@/lib/api/incident-banner'
6
7/**
8 * Cache on CDN for 5 minutes
9 * Allow serving stale content for 1 minute while revalidating
10 */
11const CACHE_CONTROL_SETTINGS = 'public, s-maxage=300, stale-while-revalidate=60'
12
13export async function OPTIONS() {
14 if (!IS_PLATFORM) return new Response(null, { status: 404 })
15 return new Response(null, {
16 status: 204,
17 headers: {
18 Allow: 'GET, HEAD, OPTIONS',
19 },
20 })
21}
22
23export async function HEAD() {
24 if (!IS_PLATFORM) return new Response(null, { status: 404 })
25 return new Response(null, {
26 status: 200,
27 headers: { 'Cache-Control': CACHE_CONTROL_SETTINGS },
28 })
29}
30
31export async function GET() {
32 if (!IS_PLATFORM) return new Response(null, { status: 404 })
33
34 try {
35 const incidents = await getBannerIncidents()
36 return NextResponse.json(
37 { incidents },
38 { headers: { 'Cache-Control': CACHE_CONTROL_SETTINGS } }
39 )
40 } catch (error) {
41 let errorCode = 500
42 const headers = new Headers()
43
44 if (error instanceof InternalServerError) {
45 if (typeof error.details?.status === 'number') errorCode = error.details.status
46 if (errorCode === 420) errorCode = 429
47 if (errorCode === 429 && typeof error.details?.retryAfter === 'string') {
48 headers.set('Retry-After', error.details.retryAfter)
49 }
50 console.error('Failed to fetch incident.io incidents: %O', {
51 message: error.message,
52 details: error.details,
53 })
54 } else {
55 console.error('Unexpected error fetching incident.io incidents: %O', error)
56 }
57
58 return NextResponse.json(
59 { error: { message: 'Internal server error' } },
60 { status: errorCode, headers }
61 )
62 }
63}