-
Notifications
You must be signed in to change notification settings - Fork 87
/
next-request.ts
132 lines (114 loc) · 3.25 KB
/
next-request.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
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
import type { Context } from '@netlify/edge-functions'
import {
addBasePath,
addLocale,
addTrailingSlash,
normalizeDataUrl,
normalizeLocalePath,
removeBasePath,
} from './util.ts'
interface I18NConfig {
defaultLocale: string
localeDetection?: false
locales: string[]
}
export interface RequestData {
geo?: {
city?: string
country?: string
region?: string
latitude?: string
longitude?: string
timezone?: string
}
headers: Record<string, string>
ip?: string
method: string
nextConfig?: {
basePath?: string
i18n?: I18NConfig | null
trailingSlash?: boolean
skipMiddlewareUrlNormalize?: boolean
}
page?: {
name?: string
params?: { [key: string]: string }
}
url: string
body?: ReadableStream<Uint8Array>
detectedLocale?: string
}
const normalizeRequestURL = (
originalURL: string,
nextConfig?: RequestData['nextConfig'],
): { url: string; detectedLocale?: string } => {
const url = new URL(originalURL)
let pathname = removeBasePath(url.pathname, nextConfig?.basePath)
// If it exists, remove the locale from the URL and store it
const { detectedLocale } = normalizeLocalePath(pathname, nextConfig?.i18n?.locales)
if (!nextConfig?.skipMiddlewareUrlNormalize) {
// We want to run middleware for data requests and expose the URL of the
// corresponding pages, so we have to normalize the URLs before running
// the handler.
pathname = normalizeDataUrl(pathname)
// Normalizing the trailing slash based on the `trailingSlash` configuration
// property from the Next.js config.
if (nextConfig?.trailingSlash) {
pathname = addTrailingSlash(pathname)
}
}
url.pathname = addBasePath(pathname, nextConfig?.basePath)
return {
url: url.toString(),
detectedLocale,
}
}
export const localizeRequest = (
url: URL,
nextConfig?: {
basePath?: string
i18n?: I18NConfig | null
},
): { localizedUrl: URL; locale?: string } => {
const localizedUrl = new URL(url)
localizedUrl.pathname = removeBasePath(localizedUrl.pathname, nextConfig?.basePath)
// Detect the locale from the URL
const { detectedLocale } = normalizeLocalePath(localizedUrl.pathname, nextConfig?.i18n?.locales)
// Add the locale to the URL if not already present
localizedUrl.pathname = addLocale(
localizedUrl.pathname,
detectedLocale ?? nextConfig?.i18n?.defaultLocale,
)
localizedUrl.pathname = addBasePath(localizedUrl.pathname, nextConfig?.basePath)
return {
localizedUrl,
locale: detectedLocale,
}
}
export const buildNextRequest = (
request: Request,
context: Context,
nextConfig?: RequestData['nextConfig'],
): RequestData => {
const { url, method, body, headers } = request
const { country, subdivision, city, latitude, longitude, timezone } = context.geo
const geo: RequestData['geo'] = {
city,
country: country?.code,
region: subdivision?.code,
latitude: latitude?.toString(),
longitude: longitude?.toString(),
timezone,
}
const { detectedLocale, url: normalizedUrl } = normalizeRequestURL(url, nextConfig)
return {
headers: Object.fromEntries(headers.entries()),
geo,
url: normalizedUrl,
method,
ip: context.ip,
body: body ?? undefined,
nextConfig,
detectedLocale,
}
}