@edgeone/opennextjs-pages 0.0.6 → 0.0.8

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.
@@ -1,4 +1,3 @@
1
- import { createServer } from 'http';
2
1
  import {
3
2
  createRequestContext,
4
3
  runWithRequestContext,
@@ -6,151 +5,19 @@ import {
6
5
  import { getTracer } from './{{cwd}}/.edgeone/dist/run/handlers/tracer.cjs'
7
6
  import * as serverHandler from './{{cwd}}/.edgeone/dist/run/handlers/server.js'
8
7
 
9
-
10
8
  process.chdir('./{{cwd}}')
11
9
 
12
10
  // Set feature flag for regional blobs
13
11
  process.env.USE_REGIONAL_BLOBS = '{{useRegionalBlobs}}'
14
12
 
15
-
16
- async function handleResponse(res, response, passHeaders = {}) {
17
- const startTime = Date.now();
18
-
19
- // 没有响应 - 404 拦截
20
- if (!response) {
21
- const requestId = passHeaders['functions-request-id'] || '';
22
- res.writeHead(404, {
23
- 'Functions-Request-Id': requestId,
24
- 'eo-pages-inner-scf-status': '404',
25
- 'eo-pages-inner-status-intercept': 'true'
26
- });
27
- res.end(JSON.stringify({
28
- error: "Not Found",
29
- message: "The requested path does not exist"
30
- }));
31
- const endTime = Date.now();
32
- console.log(`Pages response status: 404`);
33
- return;
34
- }
35
-
36
- try {
37
- if (response instanceof Response) {
38
- const requestId = passHeaders['functions-request-id'] || '';
39
- const responseStatus = response.status;
40
-
41
- const headers = Object.fromEntries(response.headers);
42
- Object.assign(headers, passHeaders);
43
-
44
- // 添加状态码区分的 headers
45
- headers['Functions-Request-Id'] = requestId;
46
-
47
- // 如果 Response 中已经设置了,使用它的值;否则使用 responseStatus
48
- if (!headers['eo-pages-inner-scf-status']) {
49
- headers['eo-pages-inner-scf-status'] = String(responseStatus);
50
- }
51
-
52
- // 如果 Response 中已经设置了,使用它的值;否则默认为 false
53
- if (!headers['eo-pages-inner-status-intercept']) {
54
- headers['eo-pages-inner-status-intercept'] = 'false';
55
- }
56
-
57
- if (response.headers.get('eop-client-geo')) {
58
- // 删除 eop-client-geo 头部
59
- response.headers.delete('eop-client-geo');
60
- }
61
- // 处理 set-cookie 头部
62
- if (response.headers.has('set-cookie')) {
63
- const cookieArr = response.headers.getSetCookie();
64
-
65
- headers['set-cookie'] = cookieArr;
66
- }
67
- // 检查是否是流式响应
68
- const isStream = response.body && (
69
- response.headers.get('content-type')?.includes('text/event-stream') ||
70
- response.headers.get('transfer-encoding')?.includes('chunked') ||
71
- response.body instanceof ReadableStream ||
72
- typeof response.body.pipe === 'function' ||
73
- response.headers.get('x-content-type-stream') === 'true'
74
- );
75
-
76
- if (isStream) {
77
- // 设置流式响应所需的头部
78
- const streamHeaders = {
79
- ...headers
80
- };
81
-
82
- if (response.headers.get('content-type')?.includes('text/event-stream')) {
83
- streamHeaders['Content-Type'] = 'text/event-stream';
84
- }
85
-
86
- res.writeHead(response.status, streamHeaders);
87
-
88
- if (typeof response.body.pipe === 'function') {
89
- response.body.pipe(res);
90
- } else {
91
- const reader = response.body.getReader();
92
- try {
93
- while (true) {
94
- const { done, value } = await reader.read();
95
- if (done) break;
96
-
97
- if (value instanceof Uint8Array || Buffer.isBuffer(value)) {
98
- res.write(value);
99
- } else {
100
- const chunk = new TextDecoder().decode(value);
101
- res.write(chunk);
102
- }
103
- }
104
- } finally {
105
- reader.releaseLock();
106
- res.end();
107
- }
108
- }
109
- } else {
110
- // 普通响应
111
- res.writeHead(response.status, headers);
112
- const body = await response.text();
113
- res.end(body);
114
- }
115
- } else {
116
- // 非 Response 对象,直接返回 JSON
117
- const requestId = passHeaders['functions-request-id'] || '';
118
- res.writeHead(200, {
119
- 'Content-Type': 'application/json',
120
- 'Functions-Request-Id': requestId,
121
- 'eo-pages-inner-scf-status': '200',
122
- 'eo-pages-inner-status-intercept': 'false'
123
- });
124
- res.end(JSON.stringify(response));
125
- }
126
- } catch (error) {
127
- // 用户函数内部错误 内部502 - 拦截
128
- const requestId = passHeaders['functions-request-id'] || '';
129
- res.writeHead(502, {
130
- 'Functions-Request-Id': requestId,
131
- 'eo-pages-inner-scf-status': '502',
132
- 'eo-pages-inner-status-intercept': 'true'
133
- });
134
- res.end(JSON.stringify({
135
- error: "Internal Server Error",
136
- message: error.message
137
- }));
138
- } finally {
139
- const endTime = Date.now();
140
- console.log(`Pages response status: ${response?.status || 'unknown'}`);
141
- }
142
- }
143
-
144
-
145
13
  let cachedHandler
146
- export default async function eoHandler (req, context) {
14
+ export default async function handler(req, context = {}) {
147
15
  const requestContext = createRequestContext(req, context)
148
16
  const tracer = getTracer()
149
17
 
150
18
  const handlerResponse = await runWithRequestContext(requestContext, () => {
151
19
  return tracer.withActiveSpan('Next.js Server Handler', async (span) => {
152
20
  if (!cachedHandler) {
153
- // const { default: handler } = await import('{{nextServerHandler}}')
154
21
  cachedHandler = serverHandler.default
155
22
  }
156
23
  const response = await cachedHandler(req, context, span, requestContext)
@@ -158,117 +25,14 @@ export default async function eoHandler (req, context) {
158
25
  })
159
26
  })
160
27
 
28
+ if (requestContext.serverTiming) {
29
+ handlerResponse.headers.set('server-timing', requestContext.serverTiming);
30
+ }
31
+
161
32
  return handlerResponse
162
33
  }
163
34
 
164
-
165
35
  export const config = {
166
36
  path: '/*',
167
37
  preferStatic: true,
168
- };
169
-
170
- const port = 9000;
171
-
172
- // 实时流转换函数
173
- function createReadableStreamFromRequest(req) {
174
- return new ReadableStream({
175
- start(controller) {
176
- req.on('data', chunk => {
177
- // 将Buffer转换为Uint8Array
178
- const uint8Array = new Uint8Array(chunk);
179
- controller.enqueue(uint8Array);
180
- });
181
-
182
- req.on('end', () => {
183
- controller.close();
184
- });
185
-
186
- req.on('error', error => {
187
- controller.error(error);
188
- });
189
- },
190
-
191
- cancel() {
192
- // 清理资源
193
- req.destroy();
194
- }
195
- });
196
- }
197
-
198
- const server = createServer(async (req, res) => {
199
- try {
200
- const requestStartTime = Date.now();
201
-
202
- // 构造 handler 需要的 req 对象(可根据需要扩展)
203
- // 用 eo-pages-host 替换 host
204
- const originalHost = req.headers['eo-pages-host'] || req.headers['host'];
205
- const handlerReq = {
206
- ...req,
207
- headers: {
208
- ...req.headers,
209
- 'accept-encoding': 'identity',
210
- 'host': originalHost,
211
- },
212
- method: req.method,
213
- url: req.url,
214
- };
215
-
216
- // 读取 body(如果有)
217
- // let body = [];
218
- // req.on('data', chunk => body.push(chunk));
219
- // await new Promise(resolve => req.on('end', resolve));
220
- // if (body.length > 0) {
221
- // handlerReq.body = Buffer.concat(body);
222
- // }
223
-
224
- handlerReq.body = createReadableStreamFromRequest(req);
225
-
226
- const response = await eoHandler(handlerReq, {});
227
-
228
- // response.headers.set('functions-request-id', req.headers['x-scf-request-id'] || '');
229
-
230
- const requestEndTime = Date.now();
231
- const url = new URL(req.url, `http://${req.headers.host}`);
232
- let pathname = url.pathname;
233
-
234
- if (pathname !== '/' && pathname.endsWith('/')) {
235
- pathname = pathname.slice(0, -1);
236
- }
237
-
238
- let fullPath = '';
239
- if (req.headers.host === 'localhost:9000') {
240
- fullPath = pathname;
241
- } else {
242
- const host = req.headers['eo-pages-host'];
243
- const xForwardedProto = req.headers['x-forwarded-proto'];
244
-
245
- fullPath = (xForwardedProto || 'https') + '://' + host + req.url;
246
-
247
- if (fullPath.endsWith('?')) {
248
- fullPath = fullPath.slice(0, -1);
249
- }
250
- }
251
-
252
- console.log(`Pages request path: ${fullPath}`);
253
-
254
- await handleResponse(res, response, {
255
- 'functions-request-id': req.headers['x-scf-request-id'] || ''
256
- });
257
- return;
258
- } catch (error) {
259
- console.log(`Pages response status: 502`);
260
- // 用户函数内部错误 内部502 - 拦截
261
- const requestId = req.headers['x-scf-request-id'] || '';
262
- res.statusCode = 502;
263
- res.setHeader('Content-Type', 'text/html; charset=utf-8');
264
- res.setHeader('Functions-Request-Id', requestId);
265
- res.setHeader('eo-pages-inner-scf-status', '502');
266
- res.setHeader('eo-pages-inner-status-intercept', 'true');
267
- res.end('<html><body><h1>Error</h1><p>'+error.message+'</p></body></html>');
268
- }
269
- });
270
-
271
- server.listen(port, () => {
272
- console.log('Server is running on http://localhost:9000');
273
- });
274
-
38
+ };
@@ -1,5 +1,4 @@
1
1
 
2
- import { createServer } from 'http';
3
2
  import {
4
3
  createRequestContext,
5
4
  runWithRequestContext,
@@ -7,141 +6,8 @@ import {
7
6
  import serverHandler from './.edgeone/dist/run/handlers/server.js';
8
7
  import { getTracer } from './.edgeone/dist/run/handlers/tracer.cjs';
9
8
 
10
-
11
- async function handleResponse(res, response, passHeaders = {}) {
12
- const startTime = Date.now();
13
-
14
- // 没有响应 - 404 拦截
15
- if (!response) {
16
- const requestId = passHeaders['functions-request-id'] || '';
17
- res.writeHead(404, {
18
- 'Functions-Request-Id': requestId,
19
- 'eo-pages-inner-scf-status': '404',
20
- 'eo-pages-inner-status-intercept': 'true'
21
- });
22
- res.end(JSON.stringify({
23
- error: "Not Found",
24
- message: "The requested path does not exist"
25
- }));
26
- const endTime = Date.now();
27
- console.log(`Pages response status: 404`);
28
- return;
29
- }
30
-
31
- try {
32
- if (response instanceof Response) {
33
- const requestId = passHeaders['functions-request-id'] || '';
34
- const responseStatus = response.status;
35
-
36
- const headers = Object.fromEntries(response.headers);
37
- Object.assign(headers, passHeaders);
38
-
39
- // 添加状态码区分的 headers
40
- headers['Functions-Request-Id'] = requestId;
41
-
42
- // 如果 Response 中已经设置了,使用它的值;否则使用 responseStatus
43
- if (!headers['eo-pages-inner-scf-status']) {
44
- headers['eo-pages-inner-scf-status'] = String(responseStatus);
45
- }
46
-
47
- // 如果 Response 中已经设置了,使用它的值;否则默认为 false
48
- if (!headers['eo-pages-inner-status-intercept']) {
49
- headers['eo-pages-inner-status-intercept'] = 'false';
50
- }
51
-
52
- // 删除内部 header
53
- if (response.headers.get('eop-client-geo')) {
54
- response.headers.delete('eop-client-geo');
55
- }
56
- // 处理 set-cookie 头部
57
- if (response.headers.has('set-cookie')) {
58
- const cookieArr = response.headers.getSetCookie();
59
- headers['set-cookie'] = cookieArr;
60
- }
61
-
62
- // 检查是否是流式响应
63
- const isStream = response.body && (
64
- response.headers.get('content-type')?.includes('text/event-stream') ||
65
- response.headers.get('transfer-encoding')?.includes('chunked') ||
66
- response.body instanceof ReadableStream ||
67
- typeof response.body.pipe === 'function' ||
68
- response.headers.get('x-content-type-stream') === 'true'
69
- );
70
-
71
- if (isStream) {
72
- // 设置流式响应所需的头部
73
- const streamHeaders = {
74
- ...headers
75
- };
76
-
77
- if (response.headers.get('content-type')?.includes('text/event-stream')) {
78
- streamHeaders['Content-Type'] = 'text/event-stream';
79
- }
80
-
81
- res.writeHead(response.status, streamHeaders);
82
-
83
- if (typeof response.body.pipe === 'function') {
84
- response.body.pipe(res);
85
- } else {
86
- const reader = response.body.getReader();
87
- try {
88
- while (true) {
89
- const { done, value } = await reader.read();
90
- if (done) break;
91
-
92
- if (value instanceof Uint8Array || Buffer.isBuffer(value)) {
93
- res.write(value);
94
- } else {
95
- const chunk = new TextDecoder().decode(value);
96
- res.write(chunk);
97
- }
98
- }
99
- } finally {
100
- reader.releaseLock();
101
- // scf可能会立即冻结环境上下文,导致后续日志无法输出,通过延时来确保日志输出
102
- setTimeout(() => {
103
- res.end();
104
- }, 1);
105
- }
106
- }
107
- } else {
108
- // 普通响应
109
- res.writeHead(response.status, headers);
110
- const body = await response.text();
111
- res.end(body);
112
- }
113
- } else {
114
- // 非 Response 对象,直接返回 JSON
115
- const requestId = passHeaders['functions-request-id'] || '';
116
- res.writeHead(200, {
117
- 'Content-Type': 'application/json',
118
- 'Functions-Request-Id': requestId,
119
- 'eo-pages-inner-scf-status': '200',
120
- 'eo-pages-inner-status-intercept': 'false'
121
- });
122
- res.end(JSON.stringify(response));
123
- }
124
- } catch (error) {
125
- // 用户函数内部错误 内部502 - 拦截
126
- const requestId = passHeaders['functions-request-id'] || '';
127
- res.writeHead(502, {
128
- 'Functions-Request-Id': requestId,
129
- 'eo-pages-inner-scf-status': '502',
130
- 'eo-pages-inner-status-intercept': 'true'
131
- });
132
- res.end(JSON.stringify({
133
- error: "Internal Server Error",
134
- message: error.message
135
- }));
136
- } finally {
137
- const endTime = Date.now();
138
- console.log(`Pages response status: ${response?.status || 'unknown'}`);
139
- }
140
- }
141
-
142
-
143
9
  process.env.USE_REGIONAL_BLOBS = 'true';
144
- export default async function handler(req, context) {
10
+ export default async function handler(req, context = {}) {
145
11
  const requestContext = createRequestContext(req, context);
146
12
  const tracer = getTracer();
147
13
 
@@ -162,115 +28,4 @@ export default async function handler(req, context) {
162
28
  export const config = {
163
29
  path: '/*',
164
30
  preferStatic: true,
165
- };
166
-
167
- const port = 9000;
168
-
169
- // 实时流转换函数
170
- function createReadableStreamFromRequest(req) {
171
- return new ReadableStream({
172
- start(controller) {
173
- req.on('data', chunk => {
174
- // 将Buffer转换为Uint8Array
175
- const uint8Array = new Uint8Array(chunk);
176
- controller.enqueue(uint8Array);
177
- });
178
-
179
- req.on('end', () => {
180
- controller.close();
181
- });
182
-
183
- req.on('error', error => {
184
- controller.error(error);
185
- });
186
- },
187
-
188
- cancel() {
189
- // 清理资源
190
- req.destroy();
191
- }
192
- });
193
- }
194
-
195
- const server = createServer(async (req, res) => {
196
- try {
197
- const requestStartTime = Date.now();
198
-
199
- // 构造 handler 需要的 req 对象(可根据需要扩展)
200
- // 用 eo-pages-host 替换 host
201
- const originalHost = req.headers['eo-pages-host'] || req.headers['host'];
202
- const handlerReq = {
203
- ...req,
204
- headers: {
205
- ...req.headers,
206
- 'accept-encoding': 'identity',
207
- 'host': originalHost,
208
- },
209
- method: req.method,
210
- url: req.url,
211
- };
212
-
213
-
214
-
215
- // 读取 body(如果有)
216
- // let body = [];
217
- // req.on('data', chunk => body.push(chunk));
218
- // await new Promise(resolve => req.on('end', resolve));
219
- // if (body.length > 0) {
220
- // handlerReq.body = Buffer.concat(body);
221
- // }
222
-
223
- handlerReq.body = createReadableStreamFromRequest(req);
224
-
225
- const response = await handler(handlerReq, {});
226
-
227
- // 不要在这里设置 functions-request-id,避免重复
228
- // response.headers.set('functions-request-id', req.headers['x-scf-request-id'] || '');
229
- // const requestEndTime = Date.now();
230
-
231
- // 解析请求路径
232
- const url = new URL(req.url, `http://${req.headers.host}`);
233
- let pathname = url.pathname;
234
-
235
- if (pathname !== '/' && pathname.endsWith('/')) {
236
- pathname = pathname.slice(0, -1);
237
- }
238
-
239
- let fullPath = '';
240
- if (req.headers.host === 'localhost:9000') {
241
- fullPath = pathname;
242
- } else {
243
- const host = req.headers['eo-pages-host'];
244
- const xForwardedProto = req.headers['x-forwarded-proto'];
245
-
246
- fullPath = (xForwardedProto || 'https') + '://' + host + req.url;
247
-
248
- if (fullPath.endsWith('?')) {
249
- fullPath = fullPath.slice(0, -1);
250
- }
251
- }
252
-
253
- console.log(`Pages request path: ${fullPath}`);
254
-
255
- // console.log(`Request processing time: ${requestEndTime - requestStartTime}ms`);
256
- await handleResponse(res, response, {
257
- 'functions-request-id': req.headers['x-scf-request-id'] || ''
258
- });
259
- return;
260
- } catch (error) {
261
- console.log(`Pages response status: 502`);
262
- // 用户函数内部错误 内部502 - 拦截
263
- const requestId = req.headers['x-scf-request-id'] || '';
264
- res.statusCode = 502;
265
- res.setHeader('Content-Type', 'text/html; charset=utf-8');
266
- res.setHeader('Functions-Request-Id', requestId);
267
- res.setHeader('eo-pages-inner-scf-status', '502');
268
- res.setHeader('eo-pages-inner-status-intercept', 'true');
269
- res.end('<html><body><h1>Error</h1><p>'+error.message+'</p></body></html>');
270
- }
271
- });
272
-
273
- server.listen(port, () => {
274
- console.log('Server is running on http://localhost:9000');
275
- });
276
-
31
+ };
package/dist/index.js CHANGED
@@ -15,6 +15,7 @@ import {
15
15
  copyStaticContent,
16
16
  copyStaticExport
17
17
  } from "./build/content/static.js";
18
+ import { compileMiddleware } from "./build/functions/middleware/middleware.js";
18
19
  import { createServerHandler } from "./build/functions/server.js";
19
20
  import { PluginContext } from "./build/plugin-context.js";
20
21
  import { createRouteMeta } from "./build/routes.js";
@@ -35,13 +36,14 @@ var onBuild = async (options) => {
35
36
  // copyStaticAssets(ctx),
36
37
  copyStaticContent(ctx),
37
38
  copyPrerenderedContent(ctx),
38
- createServerHandler(ctx)
39
+ createServerHandler(ctx),
40
+ createRouteMeta(ctx)
39
41
  ]);
40
- createRouteMeta(ctx);
41
42
  };
42
43
  var onPostBuild = async (options) => {
43
44
  console.log("onPostBuild");
44
45
  const ctx = new PluginContext(options);
46
+ compileMiddleware(ctx);
45
47
  };
46
48
  export {
47
49
  onBuild,
@@ -28,7 +28,7 @@ module.exports = __toCommonJS(tags_handler_exports);
28
28
 
29
29
  // package.json
30
30
  var name = "@edgeone/opennextjs-pages";
31
- var version = "0.0.6";
31
+ var version = "0.0.8";
32
32
 
33
33
  // src/run/handlers/tags-handler.cts
34
34
  var import_request_context = require("./request-context.cjs");
package/dist/types.js ADDED
@@ -0,0 +1,6 @@
1
+
2
+ var require = await (async () => {
3
+ var { createRequire } = await import("node:module");
4
+ return createRequire(import.meta.url);
5
+ })();
6
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edgeone/opennextjs-pages",
3
- "version": "0.0.6",
3
+ "version": "0.0.8",
4
4
  "description": "",
5
5
  "main": "./dist/index.js",
6
6
  "type": "module",