@edgeone/opennextjs-pages 0.1.4 → 0.1.5-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build/functions/middleware/compiler.js +43 -4
- package/dist/build/functions/middleware/middleware.js +12 -7
- package/dist/build/functions/middleware/polyfills/index.js +24 -0
- package/dist/build/functions/middleware/wrapper.js +116 -55
- package/dist/build/plugin-context.js +44 -13
- package/dist/build/route-utils.js +698 -0
- package/dist/build/routes.js +202 -100
- package/dist/run/handlers/tags-handler.cjs +1 -1
- package/package.json +1 -1
|
@@ -2455,11 +2455,14 @@ async function compileTurbopack(inputPath, middlewareCode, options = {}) {
|
|
|
2455
2455
|
}
|
|
2456
2456
|
const externalChunks = [];
|
|
2457
2457
|
const middlewareChunks = [];
|
|
2458
|
+
const libraryChunks = [];
|
|
2458
2459
|
for (const chunkPath of chunkPaths) {
|
|
2459
2460
|
if (chunkPath.includes("[externals]")) {
|
|
2460
2461
|
externalChunks.push(chunkPath);
|
|
2461
2462
|
} else if (chunkPath.includes("[root-of-the-server]")) {
|
|
2462
2463
|
middlewareChunks.push(chunkPath);
|
|
2464
|
+
} else {
|
|
2465
|
+
libraryChunks.push(chunkPath);
|
|
2463
2466
|
}
|
|
2464
2467
|
}
|
|
2465
2468
|
const chunksCode = [];
|
|
@@ -2474,6 +2477,17 @@ async function compileTurbopack(inputPath, middlewareCode, options = {}) {
|
|
|
2474
2477
|
warnings.push(`External chunk not found: ${fullPath}`);
|
|
2475
2478
|
}
|
|
2476
2479
|
}
|
|
2480
|
+
for (const chunkPath of libraryChunks) {
|
|
2481
|
+
const relativePath = chunkPath.replace(/^server\//, "");
|
|
2482
|
+
const fullPath = join(middlewareDir, relativePath);
|
|
2483
|
+
if (existsSync(fullPath)) {
|
|
2484
|
+
let code = readFileSync(fullPath, "utf-8");
|
|
2485
|
+
code = transformForEdgeOneRuntime(code);
|
|
2486
|
+
chunksCode.push(code);
|
|
2487
|
+
} else {
|
|
2488
|
+
warnings.push(`Library chunk not found: ${fullPath}`);
|
|
2489
|
+
}
|
|
2490
|
+
}
|
|
2477
2491
|
for (const chunkPath of middlewareChunks) {
|
|
2478
2492
|
const relativePath = chunkPath.replace(/^server\//, "");
|
|
2479
2493
|
const fullPath = join(middlewareDir, relativePath);
|
|
@@ -3650,6 +3664,22 @@ async function executeMiddleware({request}) {
|
|
|
3650
3664
|
}
|
|
3651
3665
|
} catch (e) {}
|
|
3652
3666
|
}
|
|
3667
|
+
|
|
3668
|
+
// \u4ECE EdgeOne request.eo \u83B7\u53D6 geo \u548C ip \u4FE1\u606F
|
|
3669
|
+
const eoData = request.eo || {};
|
|
3670
|
+
const eoGeo = eoData.geo || {};
|
|
3671
|
+
|
|
3672
|
+
// \u5C06 EdgeOne geo \u683C\u5F0F\u8F6C\u6362\u4E3A Next.js geo \u683C\u5F0F
|
|
3673
|
+
// EdgeOne: { countryCodeAlpha2, regionCode, cityName, latitude, longitude, ... }
|
|
3674
|
+
// Next.js: { country, region, city, latitude, longitude }
|
|
3675
|
+
const nextGeo = {
|
|
3676
|
+
country: eoGeo.countryCodeAlpha2 || undefined,
|
|
3677
|
+
region: eoGeo.regionCode || undefined,
|
|
3678
|
+
city: eoGeo.cityName || undefined,
|
|
3679
|
+
latitude: eoGeo.latitude !== undefined ? String(eoGeo.latitude) : undefined,
|
|
3680
|
+
longitude: eoGeo.longitude !== undefined ? String(eoGeo.longitude) : undefined,
|
|
3681
|
+
};
|
|
3682
|
+
const clientIp = eoData.clientIp || request.headers.get('x-forwarded-for') || '';
|
|
3653
3683
|
|
|
3654
3684
|
// \u6784\u9020\u8BF7\u6C42\u5BF9\u8C61
|
|
3655
3685
|
let nextRequest;
|
|
@@ -3659,7 +3689,9 @@ async function executeMiddleware({request}) {
|
|
|
3659
3689
|
// NextRequest \u6784\u9020\u51FD\u6570\u7B7E\u540D: new NextRequest(input, init?)
|
|
3660
3690
|
// input \u53EF\u4EE5\u662F URL \u5B57\u7B26\u4E32\u6216 Request \u5BF9\u8C61
|
|
3661
3691
|
nextRequest = new NextRequestClass(request, {
|
|
3662
|
-
nextConfig: {}
|
|
3692
|
+
nextConfig: {},
|
|
3693
|
+
geo: nextGeo,
|
|
3694
|
+
ip: clientIp
|
|
3663
3695
|
});
|
|
3664
3696
|
} catch (e) {
|
|
3665
3697
|
nextRequest = null;
|
|
@@ -3713,9 +3745,9 @@ async function executeMiddleware({request}) {
|
|
|
3713
3745
|
delete: () => {}
|
|
3714
3746
|
};
|
|
3715
3747
|
|
|
3716
|
-
// \u6DFB\u52A0 geo \u548C ip
|
|
3717
|
-
nextRequest.geo =
|
|
3718
|
-
nextRequest.ip =
|
|
3748
|
+
// \u6DFB\u52A0 geo \u548C ip\uFF08\u4F7F\u7528\u4ECE EdgeOne \u8F6C\u6362\u540E\u7684\u6570\u636E\uFF09
|
|
3749
|
+
nextRequest.geo = nextGeo;
|
|
3750
|
+
nextRequest.ip = clientIp;
|
|
3719
3751
|
}
|
|
3720
3752
|
|
|
3721
3753
|
// \u8BBE\u7F6E\u5168\u5C40 NextResponse\uFF08\u5982\u679C\u53EF\u7528\uFF09
|
|
@@ -3738,6 +3770,11 @@ async function executeMiddleware({request}) {
|
|
|
3738
3770
|
headersObj[key] = value;
|
|
3739
3771
|
});
|
|
3740
3772
|
|
|
3773
|
+
// \u6CE8\u5165 geo \u548C clientIp \u5230 headers \u4E2D
|
|
3774
|
+
// Next.js 15+ \u79FB\u9664\u4E86 request.geo \u548C request.ip\uFF0C\u7528\u6237\u9700\u8981\u4ECE headers \u4E2D\u8BFB\u53D6
|
|
3775
|
+
headersObj['geo'] = JSON.stringify(nextGeo);
|
|
3776
|
+
headersObj['clientIp'] = clientIp;
|
|
3777
|
+
|
|
3741
3778
|
// \u521B\u5EFA\u4E00\u4E2A\u53EF\u5199\u7684 request \u5305\u88C5\u5BF9\u8C61
|
|
3742
3779
|
const requestWrapper = {
|
|
3743
3780
|
url: request.url,
|
|
@@ -3747,6 +3784,8 @@ async function executeMiddleware({request}) {
|
|
|
3747
3784
|
bodyUsed: request.bodyUsed,
|
|
3748
3785
|
signal: request.signal,
|
|
3749
3786
|
nextConfig: {}, // NextURL \u6784\u9020\u51FD\u6570\u9700\u8981\u8FD9\u4E2A
|
|
3787
|
+
geo: nextGeo, // EdgeOne geo \u8F6C\u6362\u4E3A Next.js \u683C\u5F0F\uFF08\u517C\u5BB9 Next.js 14 \u53CA\u4EE5\u4E0B\uFF09
|
|
3788
|
+
ip: clientIp, // \u5BA2\u6237\u7AEF IP\uFF08\u517C\u5BB9 Next.js 14 \u53CA\u4EE5\u4E0B\uFF09
|
|
3750
3789
|
// \u4FDD\u6301\u539F\u59CB Request \u7684\u65B9\u6CD5\u53EF\u7528
|
|
3751
3790
|
clone: () => request.clone(),
|
|
3752
3791
|
arrayBuffer: () => request.arrayBuffer(),
|
|
@@ -11,16 +11,20 @@ import { compile } from "./compiler.js";
|
|
|
11
11
|
import { join } from "node:path";
|
|
12
12
|
import { existsSync, writeFileSync, mkdirSync, readFileSync } from "node:fs";
|
|
13
13
|
var compileMiddleware = async (ctx) => {
|
|
14
|
+
const nextDistDir = ctx.nextDistDir || ".next";
|
|
14
15
|
const possiblePaths = [
|
|
15
|
-
// 1. Next.js 15+: distDir/server/middleware.js (直接在
|
|
16
|
+
// 1. Next.js 15+: distDir/server/middleware.js (直接在 distDir 目录下)
|
|
16
17
|
join(ctx.distDir, "server/middleware.js"),
|
|
17
|
-
// 2. Next.js 15+: standaloneDir
|
|
18
|
-
join(ctx.standaloneDir, "
|
|
19
|
-
// 3. 旧版: standaloneDir
|
|
20
|
-
join(ctx.standaloneDir, "
|
|
18
|
+
// 2. Next.js 15+: standaloneDir/{nextDistDir}/server/middleware.js
|
|
19
|
+
join(ctx.standaloneDir, nextDistDir, "server/middleware.js"),
|
|
20
|
+
// 3. 旧版: standaloneDir/{nextDistDir}/server/src/middleware.js
|
|
21
|
+
join(ctx.standaloneDir, nextDistDir, "server/src/middleware.js"),
|
|
21
22
|
// 4. 旧版: distDir/server/src/middleware.js
|
|
22
23
|
join(ctx.distDir, "server/src/middleware.js"),
|
|
23
|
-
// 5.
|
|
24
|
+
// 5. 相对于当前工作目录(使用配置的 distDir)
|
|
25
|
+
join(process.cwd(), nextDistDir, "server/middleware.js"),
|
|
26
|
+
join(process.cwd(), nextDistDir, "server/src/middleware.js"),
|
|
27
|
+
// 6. 兼容默认 .next 目录(以防 nextDistDir 获取失败)
|
|
24
28
|
join(process.cwd(), ".next/server/middleware.js"),
|
|
25
29
|
join(process.cwd(), ".next/server/src/middleware.js")
|
|
26
30
|
];
|
|
@@ -41,7 +45,8 @@ var compileMiddleware = async (ctx) => {
|
|
|
41
45
|
mkdirSync(outputDir, { recursive: true });
|
|
42
46
|
const outputPath = join(outputDir, "compiled-middleware.js");
|
|
43
47
|
writeFileSync(outputPath, result.code || "", "utf-8");
|
|
44
|
-
const
|
|
48
|
+
const edgeoneDir = join(process.cwd(), ".edgeone");
|
|
49
|
+
const edgeFunctionPath = join(edgeoneDir, "edge-functions/index.js");
|
|
45
50
|
if (existsSync(edgeFunctionPath)) {
|
|
46
51
|
let edgeFunctionCode = readFileSync(edgeFunctionPath, "utf-8");
|
|
47
52
|
if (edgeFunctionCode.includes(`'__MIDDLEWARE_BUNDLE_CODE__'`)) {
|
|
@@ -73,6 +73,22 @@ var responsePolyfill = `
|
|
|
73
73
|
return originalRedirect.call(OriginalResponse, urlString, status);
|
|
74
74
|
};
|
|
75
75
|
|
|
76
|
+
// Response.json \u9759\u6001\u65B9\u6CD5 polyfill
|
|
77
|
+
// \u67D0\u4E9B Edge \u8FD0\u884C\u65F6\u4E0D\u652F\u6301\u8FD9\u4E2A\u8F83\u65B0\u7684 Web API
|
|
78
|
+
const patchedJson = function(data, init) {
|
|
79
|
+
const body = JSON.stringify(data);
|
|
80
|
+
const responseInit = cleanResponseInit(init) || {};
|
|
81
|
+
|
|
82
|
+
// \u8BBE\u7F6E Content-Type header
|
|
83
|
+
const headers = new Headers(responseInit.headers || {});
|
|
84
|
+
if (!headers.has('Content-Type')) {
|
|
85
|
+
headers.set('Content-Type', 'application/json');
|
|
86
|
+
}
|
|
87
|
+
responseInit.headers = headers;
|
|
88
|
+
|
|
89
|
+
return new OriginalResponse(body, responseInit);
|
|
90
|
+
};
|
|
91
|
+
|
|
76
92
|
// \u521B\u5EFA cookies \u5BF9\u8C61\u7684\u5DE5\u5382\u51FD\u6570
|
|
77
93
|
function createResponseCookies(response) {
|
|
78
94
|
const cookieStore = new Map();
|
|
@@ -137,6 +153,14 @@ var responsePolyfill = `
|
|
|
137
153
|
if (prop === 'redirect') {
|
|
138
154
|
return patchedRedirect;
|
|
139
155
|
}
|
|
156
|
+
// \u62E6\u622A json \u9759\u6001\u65B9\u6CD5\uFF08polyfill for Edge runtime\uFF09
|
|
157
|
+
if (prop === 'json') {
|
|
158
|
+
// \u5982\u679C\u539F\u751F\u652F\u6301\u5C31\u7528\u539F\u751F\u7684\uFF0C\u5426\u5219\u7528 polyfill
|
|
159
|
+
if (typeof OriginalResponse.json === 'function') {
|
|
160
|
+
return OriginalResponse.json.bind(OriginalResponse);
|
|
161
|
+
}
|
|
162
|
+
return patchedJson;
|
|
163
|
+
}
|
|
140
164
|
// \u5176\u4ED6\u9759\u6001\u65B9\u6CD5\u76F4\u63A5\u4ECE\u539F\u59CB Response \u83B7\u53D6
|
|
141
165
|
return Reflect.get(target, prop, receiver);
|
|
142
166
|
}
|
|
@@ -21,6 +21,24 @@ function getEdgeOneWrapperCode(options = {}) {
|
|
|
21
21
|
// Middleware Runner (Raw Source Mode)
|
|
22
22
|
// ============================================================
|
|
23
23
|
|
|
24
|
+
/**
|
|
25
|
+
* \u5C06 EdgeOne geo \u683C\u5F0F\u8F6C\u6362\u4E3A Next.js geo \u683C\u5F0F
|
|
26
|
+
* EdgeOne: { countryCodeAlpha2, regionCode, cityName, latitude, longitude, ... }
|
|
27
|
+
* Next.js: { country, region, city, latitude, longitude }
|
|
28
|
+
*/
|
|
29
|
+
function convertEoGeoToNextGeo(eoGeo) {
|
|
30
|
+
if (!eoGeo || typeof eoGeo !== 'object') {
|
|
31
|
+
return {};
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
country: eoGeo.countryCodeAlpha2 || undefined,
|
|
35
|
+
region: eoGeo.regionCode || undefined,
|
|
36
|
+
city: eoGeo.cityName || undefined,
|
|
37
|
+
latitude: eoGeo.latitude !== undefined ? String(eoGeo.latitude) : undefined,
|
|
38
|
+
longitude: eoGeo.longitude !== undefined ? String(eoGeo.longitude) : undefined,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
24
42
|
/**
|
|
25
43
|
* \u8FD0\u884C\u4E2D\u95F4\u4EF6\u7684\u4E3B\u51FD\u6570
|
|
26
44
|
* @param {Request} request - \u539F\u59CB\u8BF7\u6C42\u5BF9\u8C61
|
|
@@ -77,66 +95,80 @@ async function executeMiddleware({request}) {
|
|
|
77
95
|
}
|
|
78
96
|
}
|
|
79
97
|
|
|
98
|
+
// \u4ECE EdgeOne request.eo \u83B7\u53D6 geo \u548C ip \u4FE1\u606F
|
|
99
|
+
const eoData = request.eo || {};
|
|
100
|
+
const nextGeo = convertEoGeoToNextGeo(eoData.geo);
|
|
101
|
+
const clientIp = eoData.clientIp || request.headers.get('x-forwarded-for') || request.headers.get('x-real-ip') || '';
|
|
102
|
+
|
|
103
|
+
// \u521B\u5EFA\u65B0\u7684 Headers\uFF0C\u6CE8\u5165 geo \u548C clientIp
|
|
104
|
+
// Next.js 15+ \u79FB\u9664\u4E86 request.geo \u548C request.ip\uFF0C\u7528\u6237\u9700\u8981\u4ECE headers \u4E2D\u8BFB\u53D6
|
|
105
|
+
const newHeaders = new Headers(request.headers);
|
|
106
|
+
newHeaders.set('geo', JSON.stringify(nextGeo));
|
|
107
|
+
newHeaders.set('clientIp', clientIp);
|
|
108
|
+
|
|
109
|
+
// \u521B\u5EFA\u5E26\u6709\u65B0 headers \u7684 request
|
|
110
|
+
const newRequest = new Request(request.url, {
|
|
111
|
+
method: request.method,
|
|
112
|
+
headers: newHeaders,
|
|
113
|
+
body: request.body,
|
|
114
|
+
});
|
|
115
|
+
|
|
80
116
|
// \u4E3A request \u6DFB\u52A0 nextUrl \u5C5E\u6027
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
});
|
|
103
|
-
}
|
|
117
|
+
Object.defineProperty(newRequest, 'nextUrl', {
|
|
118
|
+
value: {
|
|
119
|
+
pathname: pathname,
|
|
120
|
+
search: url.search,
|
|
121
|
+
searchParams: url.searchParams,
|
|
122
|
+
hash: url.hash,
|
|
123
|
+
host: url.host,
|
|
124
|
+
hostname: url.hostname,
|
|
125
|
+
port: url.port,
|
|
126
|
+
protocol: url.protocol,
|
|
127
|
+
href: url.href,
|
|
128
|
+
origin: url.origin,
|
|
129
|
+
basePath: '',
|
|
130
|
+
locale: '',
|
|
131
|
+
defaultLocale: '',
|
|
132
|
+
toString: () => url.href,
|
|
133
|
+
clone: () => new URL(url.href)
|
|
134
|
+
},
|
|
135
|
+
writable: true,
|
|
136
|
+
enumerable: true
|
|
137
|
+
});
|
|
104
138
|
|
|
105
139
|
// \u4E3A request \u6DFB\u52A0 cookies \u5C5E\u6027
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
Object.defineProperty(request, 'cookies', {
|
|
123
|
-
value: {
|
|
124
|
-
get: (name) => cookieMap.get(name),
|
|
125
|
-
has: (name) => cookieMap.has(name),
|
|
126
|
-
getAll: () => Array.from(cookieMap.values()),
|
|
127
|
-
set: () => {},
|
|
128
|
-
delete: () => {},
|
|
129
|
-
clear: () => {},
|
|
130
|
-
[Symbol.iterator]: () => cookieMap.values(),
|
|
131
|
-
size: cookieMap.size
|
|
132
|
-
},
|
|
133
|
-
writable: true,
|
|
134
|
-
enumerable: true
|
|
140
|
+
const cookieHeader = newRequest.headers.get('cookie') || '';
|
|
141
|
+
const cookieMap = new Map();
|
|
142
|
+
|
|
143
|
+
if (cookieHeader) {
|
|
144
|
+
cookieHeader.split(';').forEach(cookie => {
|
|
145
|
+
const [name, ...valueParts] = cookie.trim().split('=');
|
|
146
|
+
if (name) {
|
|
147
|
+
cookieMap.set(name.trim(), {
|
|
148
|
+
name: name.trim(),
|
|
149
|
+
value: valueParts.join('=') || ''
|
|
150
|
+
});
|
|
151
|
+
}
|
|
135
152
|
});
|
|
136
153
|
}
|
|
154
|
+
|
|
155
|
+
Object.defineProperty(newRequest, 'cookies', {
|
|
156
|
+
value: {
|
|
157
|
+
get: (name) => cookieMap.get(name),
|
|
158
|
+
has: (name) => cookieMap.has(name),
|
|
159
|
+
getAll: () => Array.from(cookieMap.values()),
|
|
160
|
+
set: () => {},
|
|
161
|
+
delete: () => {},
|
|
162
|
+
clear: () => {},
|
|
163
|
+
[Symbol.iterator]: () => cookieMap.values(),
|
|
164
|
+
size: cookieMap.size
|
|
165
|
+
},
|
|
166
|
+
writable: true,
|
|
167
|
+
enumerable: true
|
|
168
|
+
});
|
|
137
169
|
|
|
138
170
|
// \u8C03\u7528 middleware \u51FD\u6570
|
|
139
|
-
const result = await middleware(
|
|
171
|
+
const result = await middleware(newRequest);
|
|
140
172
|
|
|
141
173
|
return result;
|
|
142
174
|
}
|
|
@@ -274,6 +306,24 @@ function matchesPath(pathname, matcher) {
|
|
|
274
306
|
return false;
|
|
275
307
|
}
|
|
276
308
|
|
|
309
|
+
/**
|
|
310
|
+
* \u5C06 EdgeOne geo \u683C\u5F0F\u8F6C\u6362\u4E3A Next.js geo \u683C\u5F0F
|
|
311
|
+
* EdgeOne: { countryCodeAlpha2, regionCode, cityName, latitude, longitude, ... }
|
|
312
|
+
* Next.js: { country, region, city, latitude, longitude }
|
|
313
|
+
*/
|
|
314
|
+
function convertEoGeoToNextGeo(eoGeo) {
|
|
315
|
+
if (!eoGeo || typeof eoGeo !== 'object') {
|
|
316
|
+
return {};
|
|
317
|
+
}
|
|
318
|
+
return {
|
|
319
|
+
country: eoGeo.countryCodeAlpha2 || undefined,
|
|
320
|
+
region: eoGeo.regionCode || undefined,
|
|
321
|
+
city: eoGeo.cityName || undefined,
|
|
322
|
+
latitude: eoGeo.latitude !== undefined ? String(eoGeo.latitude) : undefined,
|
|
323
|
+
longitude: eoGeo.longitude !== undefined ? String(eoGeo.longitude) : undefined,
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
|
|
277
327
|
/**
|
|
278
328
|
* \u8FD0\u884C\u4E2D\u95F4\u4EF6\u7684\u4E3B\u51FD\u6570
|
|
279
329
|
* @param {Request} request - \u539F\u59CB\u8BF7\u6C42\u5BF9\u8C61
|
|
@@ -298,6 +348,17 @@ async function executeMiddleware({request}) {
|
|
|
298
348
|
request.headers.forEach((value, key) => {
|
|
299
349
|
headersObject[key] = value;
|
|
300
350
|
});
|
|
351
|
+
|
|
352
|
+
// \u4ECE EdgeOne request.eo \u83B7\u53D6 geo \u548C ip \u4FE1\u606F
|
|
353
|
+
const eoData = request.eo || {};
|
|
354
|
+
const nextGeo = convertEoGeoToNextGeo(eoData.geo);
|
|
355
|
+
const clientIp = eoData.clientIp || request.headers.get('x-forwarded-for') || request.headers.get('x-real-ip') || '';
|
|
356
|
+
|
|
357
|
+
// \u6CE8\u5165 geo \u548C clientIp \u5230 headers \u4E2D
|
|
358
|
+
// Next.js 15+ \u79FB\u9664\u4E86 request.geo \u548C request.ip\uFF0C\u7528\u6237\u9700\u8981\u4ECE headers \u4E2D\u8BFB\u53D6
|
|
359
|
+
// \u4F7F\u7528 'geo' (JSON \u5B57\u7B26\u4E32) \u548C 'clientIp' \u4F5C\u4E3A header \u540D\u79F0
|
|
360
|
+
headersObject['geo'] = JSON.stringify(nextGeo);
|
|
361
|
+
headersObject['clientIp'] = clientIp;
|
|
301
362
|
|
|
302
363
|
// \u6784\u9020 Next.js middleware adapter \u671F\u671B\u7684\u53C2\u6570\u683C\u5F0F
|
|
303
364
|
// \u53C2\u8003 Next.js \u6E90\u7801\u4E2D\u7684 adapter \u51FD\u6570
|
|
@@ -312,8 +373,8 @@ async function executeMiddleware({request}) {
|
|
|
312
373
|
i18n: null,
|
|
313
374
|
trailingSlash: false
|
|
314
375
|
},
|
|
315
|
-
geo:
|
|
316
|
-
ip:
|
|
376
|
+
geo: nextGeo,
|
|
377
|
+
ip: clientIp,
|
|
317
378
|
signal: request.signal || null
|
|
318
379
|
},
|
|
319
380
|
page: '/',
|
|
@@ -22,7 +22,7 @@ import { fileURLToPath } from "node:url";
|
|
|
22
22
|
var MODULE_DIR = fileURLToPath(new URL(".", import.meta.url));
|
|
23
23
|
var PLUGIN_DIR = join(MODULE_DIR, "../..");
|
|
24
24
|
var DEFAULT_PUBLISH_DIR = ".next";
|
|
25
|
-
var SERVER_HANDLER_NAME = "
|
|
25
|
+
var SERVER_HANDLER_NAME = "cloud-functions/ssr-node";
|
|
26
26
|
var EDGE_HANDLER_NAME = "edgeone-edge-handler";
|
|
27
27
|
var PluginContext = class {
|
|
28
28
|
edgeoneConfig;
|
|
@@ -40,7 +40,7 @@ var PluginContext = class {
|
|
|
40
40
|
}
|
|
41
41
|
/** Temporary directory for stashing the build output */
|
|
42
42
|
get tempPublishDir() {
|
|
43
|
-
return this.resolveFromPackagePath(".edgeone
|
|
43
|
+
return this.resolveFromPackagePath(join(".edgeone", this.nextDistDir));
|
|
44
44
|
}
|
|
45
45
|
/** Absolute path of the publish directory */
|
|
46
46
|
get publishDir() {
|
|
@@ -152,13 +152,15 @@ var PluginContext = class {
|
|
|
152
152
|
return join(this.edgeFunctionsDir, EDGE_HANDLER_NAME);
|
|
153
153
|
}
|
|
154
154
|
constructor(options) {
|
|
155
|
+
const detectedPublishDir = this.detectPublishDir(options?.constants?.PACKAGE_PATH);
|
|
155
156
|
options = {
|
|
156
157
|
...options,
|
|
157
158
|
functions: {
|
|
158
159
|
"*": {}
|
|
159
160
|
},
|
|
160
161
|
constants: {
|
|
161
|
-
|
|
162
|
+
...options?.constants,
|
|
163
|
+
PUBLISH_DIR: detectedPublishDir
|
|
162
164
|
// BUILD_VERSION: '32.1.4',
|
|
163
165
|
}
|
|
164
166
|
};
|
|
@@ -171,6 +173,32 @@ var PluginContext = class {
|
|
|
171
173
|
this.serverlessWrapHandler = options.serverlessWrapHandler;
|
|
172
174
|
this.getRuntimeShim = options.getRuntimeShim;
|
|
173
175
|
}
|
|
176
|
+
/**
|
|
177
|
+
* 自动检测 Next.js 构建输出目录
|
|
178
|
+
* 搜索包含 BUILD_ID 文件的目录,支持自定义 distDir 配置
|
|
179
|
+
*/
|
|
180
|
+
detectPublishDir(packagePath) {
|
|
181
|
+
const basePath = packagePath || process.cwd();
|
|
182
|
+
const possibleDirs = [
|
|
183
|
+
".next",
|
|
184
|
+
// 默认
|
|
185
|
+
"build",
|
|
186
|
+
// 常见自定义
|
|
187
|
+
"dist",
|
|
188
|
+
// 常见自定义
|
|
189
|
+
"out",
|
|
190
|
+
// 常见自定义
|
|
191
|
+
".build"
|
|
192
|
+
// 其他可能
|
|
193
|
+
];
|
|
194
|
+
for (const dir of possibleDirs) {
|
|
195
|
+
const fullPath = resolve(basePath, dir);
|
|
196
|
+
if (existsSync(join(fullPath, "BUILD_ID"))) {
|
|
197
|
+
return dir;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return DEFAULT_PUBLISH_DIR;
|
|
201
|
+
}
|
|
174
202
|
/** Resolves a path correctly with mono repository awareness for .edgeone directories mainly */
|
|
175
203
|
resolveFromPackagePath(...args) {
|
|
176
204
|
return resolve(this.constants.PACKAGE_PATH || "", ...args);
|
|
@@ -201,18 +229,21 @@ var PluginContext = class {
|
|
|
201
229
|
/**
|
|
202
230
|
* Uses various heuristics to try to find the .next dir.
|
|
203
231
|
* Works by looking for BUILD_ID, so requires the site to have been built
|
|
232
|
+
* 支持自定义 distDir 配置(如 distDir: 'build')
|
|
204
233
|
*/
|
|
205
234
|
findDotNext() {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
resolve(
|
|
213
|
-
|
|
214
|
-
resolve(this.constants.PACKAGE_PATH || "",
|
|
215
|
-
|
|
235
|
+
const possibleDirNames = [".next", "build", "dist", "out", ".build"];
|
|
236
|
+
const searchDirs = [
|
|
237
|
+
// The publish directory (已检测的目录)
|
|
238
|
+
this.publishDir
|
|
239
|
+
];
|
|
240
|
+
for (const dirName of possibleDirNames) {
|
|
241
|
+
searchDirs.push(resolve(dirName));
|
|
242
|
+
searchDirs.push(resolve(this.publishDir, "..", dirName));
|
|
243
|
+
searchDirs.push(resolve(this.constants.PACKAGE_PATH || "", dirName));
|
|
244
|
+
}
|
|
245
|
+
const uniqueDirs = [...new Set(searchDirs)];
|
|
246
|
+
for (const dir of uniqueDirs) {
|
|
216
247
|
if (existsSync(join(dir, "BUILD_ID"))) {
|
|
217
248
|
return dir;
|
|
218
249
|
}
|