-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathmiddleware.ts
96 lines (74 loc) · 2.48 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
93
94
95
96
import type { NextRequest } from 'next/server';
import { NextResponse } from 'next/server';
import { Games } from './constants/Games';
import { parseSubdomain } from './helpers/parseUrl';
export const getValidSubdomain = (host?: string | null) => {
let subdomain: string | null = null;
if (!host && typeof window !== 'undefined') {
// On client side, get the host from window
host = window.location.host;
}
const hostSplit = host?.split('.');
if (host && hostSplit) {
const candidate = parseSubdomain(host);
if (candidate) {
// Valid candidate
subdomain = candidate;
}
}
return subdomain;
};
// regex for public files
const PUBLIC_FILE = /\.(.*)$/;
// pages that are allowed to be accessed without a subdomain (GameId.THINKY)
const noSubdomainPages = new Set([
'achievement',
'admin',
'api',
'confirm-email',
'forgot-password',
'login',
'notifications',
'play-as-guest',
'profile',
'reset-password',
'settings',
'signup',
]);
const validSubdomains = new Set<string>();
for (const game of Object.values(Games)) {
if (game.subdomain) {
validSubdomains.add(game.subdomain);
}
}
// https://medium.com/@jfbaraky/using-subdomains-as-paths-on-next-js-e5aab5c28c28
export async function middleware(req: NextRequest) {
const url = req.nextUrl.clone();
// skip public files
if (PUBLIC_FILE.test(url.pathname) || url.pathname.startsWith('/_next')) {
return;
}
const host = req.headers.get('host');
const validSubdomain = getValidSubdomain(host);
const subdomain = validSubdomain ? validSubdomain : 'thinky';
const folder = url.pathname.split('/')[1];
// don't redirect api calls or invalid subdomains
if (folder === 'api' || (subdomain !== null && !validSubdomains.has(subdomain))) {
return;
}
// redirect urls like thinky.gg/pathology/play to pathology.thinky.gg/play
if (!subdomain && validSubdomains.has(folder)) {
const path = url.pathname.split('/').slice(2).join('/');
return NextResponse.redirect(`${url.protocol}//${folder}.${host}/${path}`);
}
if (subdomain || noSubdomainPages.has(folder)) {
// NB: this actually updates thinky.gg/pathname pages to thinky.gg/null/pathname, so they are able to access the [subdomain] route
url.pathname = `/${subdomain}${url.pathname}`;
}
if (folder.length === 0 && subdomain === 'thinky') {
console.log('not redirecting ', folder, subdomain);
return;
}
console.log('redirecting ', folder, subdomain);
return NextResponse.rewrite(url);
}