forked from ethereum/ethereum-org-website
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathproxy.ts
More file actions
154 lines (139 loc) · 4.2 KB
/
Copy pathproxy.ts
File metadata and controls
154 lines (139 loc) · 4.2 KB
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
import { precompute } from "flags/next"
import { NextRequest, NextResponse } from "next/server"
import createMiddleware from "next-intl/middleware"
import { routing } from "./src/i18n/routing"
import {
AB_CODE_SEGMENT,
encodeABCode,
FLAG_OVERRIDE_COOKIE_PREFIX,
} from "./src/lib/ab-testing/constants"
import { abTestRoutes, ALLOW_DEBUG_OVERRIDES } from "./src/lib/ab-testing/flags"
import { getActiveExperimentNames } from "./src/lib/ab-testing/matomo-adapter"
import { DEFAULT_LOCALE } from "./src/lib/constants"
import { getFirstSegment } from "./src/lib/utils/url"
const handleI18nRouting = createMiddleware(routing)
// Locales that have been removed but may have external links pointing to them
const DEPRECATED_LOCALES = new Set([
// Previously deprecated
"pcm",
"fil",
"ph",
// Removed in locale reduction (67 → 25)
"am",
"az",
"be",
"bg",
"bs",
"ca",
"da",
"el",
"fa",
"fi",
"ga",
"gl",
"gu",
"ha",
"he",
"hr",
"hu",
"hy-am",
"ig",
"ka",
"kk",
"km",
"kn",
"lt",
"ml",
"ms",
"nb",
"ne-np",
"nl",
"no",
"pt",
"ro",
"se",
"sk",
"sl",
"sn",
"sr",
"sv",
"th",
"tk",
"tl",
"tw",
"uz",
"yo",
])
function redirectTo(request: NextRequest, pathname: string, status: number) {
const url = request.nextUrl.clone()
url.pathname = pathname
return NextResponse.redirect(url, status)
}
export default async function proxy(request: NextRequest) {
const { pathname } = request.nextUrl
const lowerPath = pathname.toLowerCase()
if (pathname !== lowerPath) {
return redirectTo(request, lowerPath, 301)
}
const firstSegment = getFirstSegment(lowerPath)
if (firstSegment && DEPRECATED_LOCALES.has(firstSegment)) {
// Strip deprecated locale and redirect to default locale version
const rest = lowerPath.slice(firstSegment.length + 1)
const newPath = !rest ? "/" : rest
return redirectTo(request, newPath, 301)
}
// A/B testing: precompute flag variants and rewrite to the coded route,
// which serves a statically generated page per variant permutation.
// Only exact canonical paths match (non-canonical forms fall through and
// get slash-normalized first). Only the default locale is A/B tested:
// English URLs are unprefixed, so locale-prefixed paths never match.
// On failure, or with no experiment running, fall through to the real page.
const routeFlags = abTestRoutes[pathname]
if (routeFlags?.length) {
try {
// Only rewrite while a test is actually running, so the deployed page
// stays authoritative before launch and after a pause. Debug overrides
// force a rewrite so variants stay previewable on non-prod deploys.
const forced =
ALLOW_DEBUG_OVERRIDES &&
routeFlags.some((flag) =>
request.cookies.has(`${FLAG_OVERRIDE_COOKIE_PREFIX}${flag.key}`)
)
const running =
forced ||
(await getActiveExperimentNames().then((active) =>
routeFlags.some((flag) => active.has(flag.key))
))
if (running) {
const code = await precompute(routeFlags)
const url = request.nextUrl.clone()
// The coded segment goes *below* the tested path, not above it, so the
// route's own layouts stay active - a coded page hoisted to the app
// root loses parallel slots like find-wallet's @modal, which breaks
// route interception for the variant being tested.
url.pathname = `/${DEFAULT_LOCALE}${pathname}${AB_CODE_SEGMENT}/${encodeABCode(code)}/`
return NextResponse.rewrite(url)
}
} catch (error) {
console.error("[proxy] A/B precompute failed:", error)
}
}
// Handle i18n routing
const response = handleI18nRouting(request)
// Upgrade default-locale strip redirects from 307 to 301 for SEO
if (response.status === 307) {
const pathname = request.nextUrl.pathname
const defaultPrefix = `/${DEFAULT_LOCALE}`
if (
pathname === defaultPrefix ||
pathname.startsWith(`${defaultPrefix}/`)
) {
return new NextResponse(null, { status: 301, headers: response.headers })
}
}
return response
}
// Simplified matcher pattern
export const config = {
matcher: ["/((?!api|_next|_vercel|.well-known|.*\\.[^/]*$).*)"],
}