Skip to content

Commit 7bb6166

Browse files
committed
Fetch and cache all verified domains; allow only verified domains
1 parent cada0ee commit 7bb6166

File tree

2 files changed

+65
-11
lines changed

2 files changed

+65
-11
lines changed

middleware.js

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { NextResponse, URLPattern } from 'next/server'
2+
import { cachedFetcher } from '@/lib/fetch'
23
const referrerPattern = new URLPattern({ pathname: ':pathname(*)/r/:referrer([\\w_]+)' })
34
const itemPattern = new URLPattern({ pathname: '/items/:id(\\d+){/:other(\\w+)}?' })
45
const profilePattern = new URLPattern({ pathname: '/:name([\\w_]+){/:type(\\w+)}?' })
@@ -14,15 +15,29 @@ const SN_REFEREE_LANDING = 'sn_referee_landing'
1415
const TERRITORY_PATHS = ['/~', '/recent', '/random', '/top', '/post', '/edit']
1516
const NO_REWRITE_PATHS = ['/api', '/_next', '/_error', '/404', '/500', '/offline', '/static', '/items']
1617

17-
function getDomainMapping () {
18-
// placeholder for cachedFetcher
19-
return {
20-
'forum.pizza.com': { subName: 'pizza' }
21-
// placeholder for other domains
18+
// fetch custom domain mappings from our API, caching it for 5 minutes
19+
const getDomainMappingsCache = cachedFetcher(async function fetchDomainMappings () {
20+
const url = `${process.env.NEXT_PUBLIC_URL}/api/domains/map`
21+
try {
22+
const response = await fetch(url)
23+
if (!response.ok) {
24+
console.error(`Cannot fetch domain mappings: ${response.status} ${response.statusText}`)
25+
return null
26+
}
27+
28+
const data = await response.json()
29+
return Object.keys(data).length > 0 ? data : null
30+
} catch (error) {
31+
console.error('Cannot fetch domain mappings:', error)
32+
return null
2233
}
23-
}
34+
}, {
35+
cacheExpiry: 300000, // 5 minutes cache
36+
forceRefreshThreshold: 600000, // 10 minutes before force refresh
37+
keyGenerator: () => 'domain_mappings'
38+
})
2439

25-
export function customDomainMiddleware (request, referrerResp) {
40+
export async function customDomainMiddleware (request, referrerResp) {
2641
const host = request.headers.get('host')
2742
const referer = request.headers.get('referer')
2843
const url = request.nextUrl.clone()
@@ -33,8 +48,8 @@ export function customDomainMiddleware (request, referrerResp) {
3348

3449
console.log('referer', referer)
3550

36-
const domainMapping = getDomainMapping() // placeholder
37-
const domainInfo = domainMapping[host.toLowerCase()]
51+
const domainMapping = await getDomainMappingsCache()
52+
const domainInfo = domainMapping?.[host.toLowerCase()]
3853
if (!domainInfo) {
3954
return NextResponse.redirect(new URL(pathname, mainDomain))
4055
}
@@ -250,7 +265,7 @@ export function applySecurityHeaders (resp) {
250265
return resp
251266
}
252267

253-
export function middleware (request) {
268+
export async function middleware (request) {
254269
const host = request.headers.get('host')
255270
const isCustomDomain = host !== process.env.NEXT_PUBLIC_URL.replace(/^https?:\/\//, '')
256271

@@ -259,7 +274,7 @@ export function middleware (request) {
259274

260275
// If we're on a custom domain, handle that next
261276
if (isCustomDomain) {
262-
const customDomainResp = customDomainMiddleware(request, referrerResp)
277+
const customDomainResp = await customDomainMiddleware(request, referrerResp)
263278
return applySecurityHeaders(customDomainResp)
264279
}
265280

pages/api/domains/index.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import prisma from '@/api/models'
2+
3+
// TODO: Authentication for this?
4+
export default async function handler (req, res) {
5+
res.setHeader('Access-Control-Allow-Origin', '*')
6+
res.setHeader('Access-Control-Allow-Methods', 'GET')
7+
res.setHeader('Access-Control-Allow-Headers', 'Content-Type')
8+
9+
// Only allow GET requests
10+
if (req.method !== 'GET') {
11+
return res.status(405).json({ error: 'Method not allowed' })
12+
}
13+
14+
try {
15+
// fetch all custom domains from the database
16+
const domains = await prisma.customDomain.findMany({
17+
select: {
18+
domain: true,
19+
subName: true
20+
},
21+
where: {
22+
verificationState: 'VERIFIED'
23+
}
24+
})
25+
26+
// map domains to a key-value pair
27+
const domainMappings = domains.reduce((acc, domain) => {
28+
acc[domain.domain.toLowerCase()] = {
29+
subName: domain.subName
30+
}
31+
return acc
32+
}, {})
33+
34+
return res.status(200).json(domainMappings)
35+
} catch (error) {
36+
console.error('cannot fetch domains:', error)
37+
return res.status(500).json({ error: 'Failed to fetch domains' })
38+
}
39+
}

0 commit comments

Comments
 (0)