-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmiddleware.ts
92 lines (75 loc) · 2.8 KB
/
middleware.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
function isCustomDomain(hostname: string): boolean {
const normalizedHost = hostname.split(':')[0].toLowerCase()
return !(
normalizedHost === 'tiny.pm' ||
normalizedHost.endsWith('.tiny.pm') ||
normalizedHost === 'localhost' ||
normalizedHost.includes('192.') ||
normalizedHost.includes('127.0.0.1')
)
}
function rewriteToMainDomain(request: NextRequest, username: string | null = null) {
const url = request.nextUrl.clone()
// If it's a static asset, inject tiny.pm into the URL
if (url.pathname.startsWith('/_next')) {
const response = NextResponse.next()
// Rewrite the HTML to point static assets to tiny.pm
response.headers.set(
'Link',
`<https://tiny.pm${url.pathname}>; rel=preload; as=${getAssetType(url.pathname)}`
)
return response
}
// For other requests, rewrite to the user's path if username is provided
if (username) {
url.pathname = `/${username}${url.pathname}`
}
const response = NextResponse.rewrite(url)
// Add header to tell the client to load assets from tiny.pm
response.headers.set('X-Asset-Domain', 'https://tiny.pm')
return response
}
function getAssetType(pathname: string): string {
if (pathname.endsWith('.js')) return 'script'
if (pathname.endsWith('.css')) return 'style'
if (pathname.endsWith('.woff') || pathname.endsWith('.woff2')) return 'font'
if (pathname.endsWith('.png') || pathname.endsWith('.jpg') || pathname.endsWith('.jpeg') || pathname.endsWith('.gif') || pathname.endsWith('.webp')) return 'image'
return 'fetch'
}
export async function middleware(request: NextRequest) {
const hostname = request.headers.get('host') || '';
// Only proceed if this is a custom domain
if (!isCustomDomain(hostname)) {
return NextResponse.next();
}
try {
// Verify domain and get username
const verifyUrl = `https://tiny.pm/api/domains/verify?domain=${hostname}`;
const response = await fetch(verifyUrl);
const data = await response.json();
if (!data.username) {
return new NextResponse('Domain not found', { status: 404 });
}
// Create the rewrite URL
const url = request.nextUrl.clone();
url.pathname = `/${data.username}${request.nextUrl.pathname}`;
return NextResponse.rewrite(url);
} catch (error) {
console.error('[Middleware] Error:', error);
return new NextResponse('Internal Server Error', { status: 500 });
}
}
export const config = {
matcher: [
/*
* Match all request paths except for the ones starting with:
* - api (API routes)
* - _next/static (static files)
* - _next/image (image optimization files)
* - favicon.ico (favicon file)
*/
'/((?!api|_next/static|_next/image|favicon.ico).*)'
],
};