vafast 0.3.2 → 0.3.4
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/auth/token.d.ts +13 -11
- package/dist/auth/token.js +118 -111
- package/dist/auth/token.js.map +1 -0
- package/dist/defineRoute.d.ts +5 -2
- package/dist/defineRoute.js +7 -2
- package/dist/defineRoute.js.map +1 -0
- package/dist/index.d.ts +30 -14
- package/dist/index.js +2247 -15
- package/dist/index.js.map +1 -0
- package/dist/middleware/auth.d.ts +8 -6
- package/dist/middleware/auth.js +198 -99
- package/dist/middleware/auth.js.map +1 -0
- package/dist/middleware/authMiddleware.d.ts +5 -2
- package/dist/middleware/authMiddleware.js +55 -11
- package/dist/middleware/authMiddleware.js.map +1 -0
- package/dist/middleware/component-renderer.d.ts +4 -2
- package/dist/middleware/component-renderer.js +87 -80
- package/dist/middleware/component-renderer.js.map +1 -0
- package/dist/middleware/component-router.d.ts +8 -3
- package/dist/middleware/component-router.js +33 -39
- package/dist/middleware/component-router.js.map +1 -0
- package/dist/middleware/cors.d.ts +6 -3
- package/dist/middleware/cors.js +42 -29
- package/dist/middleware/cors.js.map +1 -0
- package/dist/middleware/rateLimit.d.ts +5 -3
- package/dist/middleware/rateLimit.js +45 -29
- package/dist/middleware/rateLimit.js.map +1 -0
- package/dist/middleware.d.ts +6 -3
- package/dist/middleware.js +97 -51
- package/dist/middleware.js.map +1 -0
- package/dist/monitoring/index.d.ts +11 -4
- package/dist/monitoring/index.js +1299 -17
- package/dist/monitoring/index.js.map +1 -0
- package/dist/monitoring/native-monitor.d.ts +12 -6
- package/dist/monitoring/native-monitor.js +1258 -161
- package/dist/monitoring/native-monitor.js.map +1 -0
- package/dist/monitoring/types.d.ts +8 -6
- package/dist/monitoring/types.js +1 -1
- package/dist/monitoring/types.js.map +1 -0
- package/dist/node-server/index.d.ts +4 -22
- package/dist/node-server/index.js +254 -21
- package/dist/node-server/index.js.map +1 -0
- package/dist/node-server/request.d.ts +6 -2
- package/dist/node-server/request.js +102 -134
- package/dist/node-server/request.js.map +1 -0
- package/dist/node-server/response.d.ts +7 -3
- package/dist/node-server/response.js +67 -89
- package/dist/node-server/response.js.map +1 -0
- package/dist/node-server/serve.d.ts +11 -7
- package/dist/node-server/serve.js +231 -82
- package/dist/node-server/serve.js.map +1 -0
- package/dist/router/index.d.ts +3 -5
- package/dist/router/index.js +228 -7
- package/dist/router/index.js.map +1 -0
- package/dist/router/radix-tree.d.ts +7 -4
- package/dist/router/radix-tree.js +186 -218
- package/dist/router/radix-tree.js.map +1 -0
- package/dist/router.d.ts +7 -3
- package/dist/router.js +37 -83
- package/dist/router.js.map +1 -0
- package/dist/serve.d.ts +2 -12
- package/dist/serve.js +237 -11
- package/dist/serve.js.map +1 -0
- package/dist/server/base-server.d.ts +5 -2
- package/dist/server/base-server.js +124 -135
- package/dist/server/base-server.js.map +1 -0
- package/dist/server/component-server.d.ts +9 -4
- package/dist/server/component-server.js +481 -139
- package/dist/server/component-server.js.map +1 -0
- package/dist/server/index.d.ts +8 -7
- package/dist/server/index.js +985 -11
- package/dist/server/index.js.map +1 -0
- package/dist/server/server-factory.d.ts +11 -5
- package/dist/server/server-factory.js +979 -67
- package/dist/server/server-factory.js.map +1 -0
- package/dist/server/server.d.ts +7 -3
- package/dist/server/server.js +553 -112
- package/dist/server/server.js.map +1 -0
- package/dist/types/component-route.d.ts +8 -4
- package/dist/types/component-route.js +1 -1
- package/dist/types/component-route.js.map +1 -0
- package/dist/types/index.d.ts +5 -5
- package/dist/types/index.js +21 -4
- package/dist/types/index.js.map +1 -0
- package/dist/types/route.d.ts +13 -10
- package/dist/types/route.js +10 -9
- package/dist/types/route.js.map +1 -0
- package/dist/types/schema.d.ts +11 -7
- package/dist/types/schema.js +1 -1
- package/dist/types/schema.js.map +1 -0
- package/dist/types/types.d.ts +11 -9
- package/dist/types/types.js +1 -1
- package/dist/types/types.js.map +1 -0
- package/dist/utils/base64url.d.ts +4 -2
- package/dist/utils/base64url.js +12 -9
- package/dist/utils/base64url.js.map +1 -0
- package/dist/utils/create-handler.d.ts +11 -7
- package/dist/utils/create-handler.js +393 -217
- package/dist/utils/create-handler.js.map +1 -0
- package/dist/utils/dependency-manager.d.ts +3 -1
- package/dist/utils/dependency-manager.js +67 -69
- package/dist/utils/dependency-manager.js.map +1 -0
- package/dist/utils/go-await.d.ts +3 -1
- package/dist/utils/go-await.js +8 -22
- package/dist/utils/go-await.js.map +1 -0
- package/dist/utils/handle.d.ts +6 -4
- package/dist/utils/handle.js +44 -25
- package/dist/utils/handle.js.map +1 -0
- package/dist/utils/html-renderer.d.ts +3 -1
- package/dist/utils/html-renderer.js +25 -24
- package/dist/utils/html-renderer.js.map +1 -0
- package/dist/utils/index.d.ts +13 -13
- package/dist/utils/index.js +832 -21
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/parsers.d.ts +15 -13
- package/dist/utils/parsers.js +138 -188
- package/dist/utils/parsers.js.map +1 -0
- package/dist/utils/path-matcher.d.ts +3 -1
- package/dist/utils/path-matcher.js +68 -78
- package/dist/utils/path-matcher.js.map +1 -0
- package/dist/utils/request-validator.d.ts +13 -10
- package/dist/utils/request-validator.js +234 -84
- package/dist/utils/request-validator.js.map +1 -0
- package/dist/utils/response.d.ts +9 -7
- package/dist/utils/response.js +93 -102
- package/dist/utils/response.js.map +1 -0
- package/dist/utils/validators/schema-validator.d.ts +13 -9
- package/dist/utils/validators/schema-validator.js +228 -209
- package/dist/utils/validators/schema-validator.js.map +1 -0
- package/dist/utils/validators/schema-validators-ultra.d.ts +15 -12
- package/dist/utils/validators/schema-validators-ultra.js +233 -256
- package/dist/utils/validators/schema-validators-ultra.js.map +1 -0
- package/dist/utils/validators/validators.d.ts +15 -12
- package/dist/utils/validators/validators.js +81 -122
- package/dist/utils/validators/validators.js.map +1 -0
- package/package.json +5 -4
|
@@ -1,157 +1,125 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const requestCache = Symbol("requestCache");
|
|
8
|
-
const incomingKey = Symbol("incoming");
|
|
9
|
-
const urlKey = Symbol("url");
|
|
10
|
-
const headersKey = Symbol("headers");
|
|
11
|
-
/**
|
|
12
|
-
* 从 rawHeaders 高效解析 Headers
|
|
13
|
-
*/
|
|
1
|
+
// src/node-server/request.ts
|
|
2
|
+
import { Readable } from "stream";
|
|
3
|
+
var requestCache = /* @__PURE__ */ Symbol("requestCache");
|
|
4
|
+
var incomingKey = /* @__PURE__ */ Symbol("incoming");
|
|
5
|
+
var urlKey = /* @__PURE__ */ Symbol("url");
|
|
6
|
+
var headersKey = /* @__PURE__ */ Symbol("headers");
|
|
14
7
|
function parseHeaders(rawHeaders) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
headers.append(key, value);
|
|
22
|
-
}
|
|
8
|
+
const headers = new Headers();
|
|
9
|
+
for (let i = 0; i < rawHeaders.length; i += 2) {
|
|
10
|
+
const key = rawHeaders[i];
|
|
11
|
+
const value = rawHeaders[i + 1];
|
|
12
|
+
if (key.charCodeAt(0) !== 58) {
|
|
13
|
+
headers.append(key, value);
|
|
23
14
|
}
|
|
24
|
-
|
|
15
|
+
}
|
|
16
|
+
return headers;
|
|
25
17
|
}
|
|
26
|
-
/**
|
|
27
|
-
* 将 Node.js ReadableStream 转换为 Web 标准 ReadableStream
|
|
28
|
-
* Node.js 和 Web 标准的 ReadableStream 在运行时兼容,但 TypeScript 类型不同
|
|
29
|
-
*/
|
|
30
18
|
function toWebStream(nodeStream) {
|
|
31
|
-
|
|
32
|
-
// 这里使用类型断言是安全的,因为 Node.js >= 18 的 stream/web 完全实现了 WHATWG Streams 标准
|
|
33
|
-
return nodeStream;
|
|
19
|
+
return nodeStream;
|
|
34
20
|
}
|
|
35
|
-
/**
|
|
36
|
-
* 创建真实的 Request 对象
|
|
37
|
-
*/
|
|
38
21
|
function createRealRequest(proxy) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
22
|
+
const incoming = proxy[incomingKey];
|
|
23
|
+
const method = incoming.method || "GET";
|
|
24
|
+
const init = {
|
|
25
|
+
method,
|
|
26
|
+
headers: proxy[headersKey] || parseHeaders(incoming.rawHeaders)
|
|
27
|
+
};
|
|
28
|
+
if (method !== "GET" && method !== "HEAD") {
|
|
29
|
+
const nodeWebStream = Readable.toWeb(
|
|
30
|
+
incoming
|
|
31
|
+
);
|
|
32
|
+
init.body = toWebStream(nodeWebStream);
|
|
33
|
+
init.duplex = "half";
|
|
34
|
+
}
|
|
35
|
+
return new Request(proxy[urlKey], init);
|
|
53
36
|
}
|
|
54
|
-
|
|
55
|
-
* Request 代理原型
|
|
56
|
-
* 使用 Object.defineProperty 定义属性以支持 this 绑定
|
|
57
|
-
*/
|
|
58
|
-
const requestPrototype = {};
|
|
59
|
-
// 定义 method 属性
|
|
37
|
+
var requestPrototype = {};
|
|
60
38
|
Object.defineProperty(requestPrototype, "method", {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
39
|
+
get() {
|
|
40
|
+
const self = this;
|
|
41
|
+
return self[incomingKey].method || "GET";
|
|
42
|
+
},
|
|
43
|
+
enumerable: true
|
|
66
44
|
});
|
|
67
|
-
// 定义 url 属性
|
|
68
45
|
Object.defineProperty(requestPrototype, "url", {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
46
|
+
get() {
|
|
47
|
+
const self = this;
|
|
48
|
+
return self[urlKey];
|
|
49
|
+
},
|
|
50
|
+
enumerable: true
|
|
74
51
|
});
|
|
75
|
-
// 定义 headers 属性(延迟解析)
|
|
76
52
|
Object.defineProperty(requestPrototype, "headers", {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
53
|
+
get() {
|
|
54
|
+
const self = this;
|
|
55
|
+
if (!self[headersKey]) {
|
|
56
|
+
self[headersKey] = parseHeaders(self[incomingKey].rawHeaders);
|
|
57
|
+
}
|
|
58
|
+
return self[headersKey];
|
|
59
|
+
},
|
|
60
|
+
enumerable: true
|
|
85
61
|
});
|
|
86
|
-
// 定义 _getRequest 方法(获取或创建真实 Request)
|
|
87
62
|
Object.defineProperty(requestPrototype, "_getRequest", {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
63
|
+
value: function() {
|
|
64
|
+
const self = this;
|
|
65
|
+
if (!self[requestCache]) {
|
|
66
|
+
self[requestCache] = createRealRequest(self);
|
|
67
|
+
}
|
|
68
|
+
return self[requestCache];
|
|
69
|
+
},
|
|
70
|
+
enumerable: false
|
|
96
71
|
});
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
"keepalive",
|
|
72
|
+
var proxyGetters = [
|
|
73
|
+
"body",
|
|
74
|
+
"bodyUsed",
|
|
75
|
+
"signal",
|
|
76
|
+
"cache",
|
|
77
|
+
"credentials",
|
|
78
|
+
"destination",
|
|
79
|
+
"integrity",
|
|
80
|
+
"mode",
|
|
81
|
+
"redirect",
|
|
82
|
+
"referrer",
|
|
83
|
+
"referrerPolicy",
|
|
84
|
+
"keepalive"
|
|
111
85
|
];
|
|
112
86
|
proxyGetters.forEach((key) => {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
87
|
+
Object.defineProperty(requestPrototype, key, {
|
|
88
|
+
get() {
|
|
89
|
+
const self = this;
|
|
90
|
+
return self._getRequest()[key];
|
|
91
|
+
},
|
|
92
|
+
enumerable: true
|
|
93
|
+
});
|
|
120
94
|
});
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
"text",
|
|
95
|
+
var proxyMethods = [
|
|
96
|
+
"arrayBuffer",
|
|
97
|
+
"blob",
|
|
98
|
+
"clone",
|
|
99
|
+
"formData",
|
|
100
|
+
"json",
|
|
101
|
+
"text"
|
|
129
102
|
];
|
|
130
103
|
proxyMethods.forEach((key) => {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
104
|
+
Object.defineProperty(requestPrototype, key, {
|
|
105
|
+
value: function() {
|
|
106
|
+
const self = this;
|
|
107
|
+
const req = self._getRequest();
|
|
108
|
+
return req[key].call(req);
|
|
109
|
+
},
|
|
110
|
+
enumerable: true
|
|
111
|
+
});
|
|
139
112
|
});
|
|
140
|
-
// 设置原型链
|
|
141
113
|
Object.setPrototypeOf(requestPrototype, Request.prototype);
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
req[incomingKey] = incoming;
|
|
150
|
-
// 构建 URL
|
|
151
|
-
const host = incoming.headers.host || defaultHost;
|
|
152
|
-
const protocol = incoming.socket.encrypted
|
|
153
|
-
? "https"
|
|
154
|
-
: "http";
|
|
155
|
-
req[urlKey] = `${protocol}://${host}${incoming.url || "/"}`;
|
|
156
|
-
return req;
|
|
114
|
+
function createProxyRequest(incoming, defaultHost) {
|
|
115
|
+
const req = Object.create(requestPrototype);
|
|
116
|
+
req[incomingKey] = incoming;
|
|
117
|
+
const host = incoming.headers.host || defaultHost;
|
|
118
|
+
const protocol = incoming.socket.encrypted ? "https" : "http";
|
|
119
|
+
req[urlKey] = `${protocol}://${host}${incoming.url || "/"}`;
|
|
120
|
+
return req;
|
|
157
121
|
}
|
|
122
|
+
export {
|
|
123
|
+
createProxyRequest
|
|
124
|
+
};
|
|
125
|
+
//# sourceMappingURL=request.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/node-server/request.ts"],"sourcesContent":["/**\n * 优化的 Request 代理\n * 延迟创建真实 Request,减少不必要的对象分配\n */\n\nimport { Readable } from \"node:stream\";\nimport type { ReadableStream as NodeReadableStream } from \"node:stream/web\";\nimport type { IncomingMessage } from \"node:http\";\n\n// 内部 Symbol\nconst requestCache = Symbol(\"requestCache\");\nconst incomingKey = Symbol(\"incoming\");\nconst urlKey = Symbol(\"url\");\nconst headersKey = Symbol(\"headers\");\n\n/**\n * 从 rawHeaders 高效解析 Headers\n */\nfunction parseHeaders(rawHeaders: string[]): Headers {\n const headers = new Headers();\n for (let i = 0; i < rawHeaders.length; i += 2) {\n const key = rawHeaders[i];\n const value = rawHeaders[i + 1];\n // 跳过 HTTP/2 伪头 (以 : 开头)\n if (key.charCodeAt(0) !== 58) {\n headers.append(key, value);\n }\n }\n return headers;\n}\n\n/**\n * 将 Node.js ReadableStream 转换为 Web 标准 ReadableStream\n * Node.js 和 Web 标准的 ReadableStream 在运行时兼容,但 TypeScript 类型不同\n */\nfunction toWebStream(\n nodeStream: NodeReadableStream<Uint8Array>,\n): ReadableStream<Uint8Array> {\n // Node.js ReadableStream 和 Web ReadableStream 在运行时是兼容的\n // 这里使用类型断言是安全的,因为 Node.js >= 18 的 stream/web 完全实现了 WHATWG Streams 标准\n return nodeStream as unknown as ReadableStream<Uint8Array>;\n}\n\n/** 代理 Request 内部接口 */\ninterface ProxyRequestInternal {\n [requestCache]?: Request;\n [incomingKey]: IncomingMessage;\n [urlKey]: string;\n [headersKey]?: Headers;\n _getRequest(): Request;\n}\n\n/**\n * 创建真实的 Request 对象\n */\nfunction createRealRequest(proxy: ProxyRequestInternal): Request {\n const incoming = proxy[incomingKey];\n const method = incoming.method || \"GET\";\n const init: RequestInit & { duplex?: string } = {\n method,\n headers: proxy[headersKey] || parseHeaders(incoming.rawHeaders),\n };\n\n // 只有非 GET/HEAD 请求才有 body\n if (method !== \"GET\" && method !== \"HEAD\") {\n // 使用 Node.js 原生流转换,避免收集 chunks\n const nodeWebStream = Readable.toWeb(\n incoming,\n ) as NodeReadableStream<Uint8Array>;\n init.body = toWebStream(nodeWebStream);\n init.duplex = \"half\";\n }\n\n return new Request(proxy[urlKey], init);\n}\n\n/**\n * Request 代理原型\n * 使用 Object.defineProperty 定义属性以支持 this 绑定\n */\nconst requestPrototype: object = {};\n\n// 定义 method 属性\nObject.defineProperty(requestPrototype, \"method\", {\n get() {\n const self = this as ProxyRequestInternal;\n return self[incomingKey].method || \"GET\";\n },\n enumerable: true,\n});\n\n// 定义 url 属性\nObject.defineProperty(requestPrototype, \"url\", {\n get() {\n const self = this as ProxyRequestInternal;\n return self[urlKey];\n },\n enumerable: true,\n});\n\n// 定义 headers 属性(延迟解析)\nObject.defineProperty(requestPrototype, \"headers\", {\n get() {\n const self = this as ProxyRequestInternal;\n if (!self[headersKey]) {\n self[headersKey] = parseHeaders(self[incomingKey].rawHeaders);\n }\n return self[headersKey];\n },\n enumerable: true,\n});\n\n// 定义 _getRequest 方法(获取或创建真实 Request)\nObject.defineProperty(requestPrototype, \"_getRequest\", {\n value: function () {\n const self = this as ProxyRequestInternal;\n if (!self[requestCache]) {\n self[requestCache] = createRealRequest(self);\n }\n return self[requestCache]!;\n },\n enumerable: false,\n});\n\n// 代理需要访问真实 Request 的属性\nconst proxyGetters = [\n \"body\",\n \"bodyUsed\",\n \"signal\",\n \"cache\",\n \"credentials\",\n \"destination\",\n \"integrity\",\n \"mode\",\n \"redirect\",\n \"referrer\",\n \"referrerPolicy\",\n \"keepalive\",\n];\n\nproxyGetters.forEach((key) => {\n Object.defineProperty(requestPrototype, key, {\n get() {\n const self = this as ProxyRequestInternal;\n return self._getRequest()[key as keyof Request];\n },\n enumerable: true,\n });\n});\n\n// 代理需要调用真实 Request 的方法\nconst proxyMethods = [\n \"arrayBuffer\",\n \"blob\",\n \"clone\",\n \"formData\",\n \"json\",\n \"text\",\n];\n\nproxyMethods.forEach((key) => {\n Object.defineProperty(requestPrototype, key, {\n value: function () {\n const self = this as ProxyRequestInternal;\n const req = self._getRequest();\n return (req[key as keyof Request] as () => Promise<unknown>).call(req);\n },\n enumerable: true,\n });\n});\n\n// 设置原型链\nObject.setPrototypeOf(requestPrototype, Request.prototype);\n\n/**\n * 创建代理 Request\n * @param incoming Node.js IncomingMessage\n * @param defaultHost 默认主机名\n */\nexport function createProxyRequest(\n incoming: IncomingMessage,\n defaultHost: string,\n): Request {\n const req = Object.create(requestPrototype) as ProxyRequestInternal;\n req[incomingKey] = incoming;\n\n // 构建 URL\n const host = incoming.headers.host || defaultHost;\n const protocol = (incoming.socket as { encrypted?: boolean }).encrypted\n ? \"https\"\n : \"http\";\n req[urlKey] = `${protocol}://${host}${incoming.url || \"/\"}`;\n\n return req as unknown as Request;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,15 +1,19 @@
|
|
|
1
|
+
import { ServerResponse } from 'node:http';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* 优化的 Response 写入
|
|
3
5
|
* 流式写入,避免内存拷贝
|
|
4
6
|
*/
|
|
5
|
-
|
|
7
|
+
|
|
6
8
|
/**
|
|
7
9
|
* 将 Web Response 写入 Node.js ServerResponse
|
|
8
10
|
* 流式写入,零拷贝
|
|
9
11
|
*/
|
|
10
|
-
|
|
12
|
+
declare function writeResponse(response: Response, outgoing: ServerResponse): Promise<void>;
|
|
11
13
|
/**
|
|
12
14
|
* 简化版写入(用于已知小体积响应)
|
|
13
15
|
* 直接 arrayBuffer 转换,适用于确定的小响应
|
|
14
16
|
*/
|
|
15
|
-
|
|
17
|
+
declare function writeResponseSimple(response: Response, outgoing: ServerResponse): Promise<void>;
|
|
18
|
+
|
|
19
|
+
export { writeResponse, writeResponseSimple };
|
|
@@ -1,98 +1,76 @@
|
|
|
1
|
-
|
|
2
|
-
* 优化的 Response 写入
|
|
3
|
-
* 流式写入,避免内存拷贝
|
|
4
|
-
*/
|
|
5
|
-
/**
|
|
6
|
-
* 构建 Node.js 响应头
|
|
7
|
-
* 处理 set-cookie 多值情况
|
|
8
|
-
*/
|
|
1
|
+
// src/node-server/response.ts
|
|
9
2
|
function buildOutgoingHeaders(headers) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
result[key] = value;
|
|
18
|
-
}
|
|
19
|
-
});
|
|
20
|
-
if (cookies.length > 0) {
|
|
21
|
-
result["set-cookie"] = cookies;
|
|
3
|
+
const result = {};
|
|
4
|
+
const cookies = [];
|
|
5
|
+
headers.forEach((value, key) => {
|
|
6
|
+
if (key === "set-cookie") {
|
|
7
|
+
cookies.push(value);
|
|
8
|
+
} else {
|
|
9
|
+
result[key] = value;
|
|
22
10
|
}
|
|
23
|
-
|
|
11
|
+
});
|
|
12
|
+
if (cookies.length > 0) {
|
|
13
|
+
result["set-cookie"] = cookies;
|
|
14
|
+
}
|
|
15
|
+
return result;
|
|
24
16
|
}
|
|
25
|
-
/**
|
|
26
|
-
* 流式写入 Response body 到 ServerResponse
|
|
27
|
-
* 支持背压处理,避免内存溢出
|
|
28
|
-
*/
|
|
29
17
|
async function writeBodyStream(body, outgoing) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
finally {
|
|
47
|
-
reader.releaseLock();
|
|
18
|
+
const reader = body.getReader();
|
|
19
|
+
try {
|
|
20
|
+
while (true) {
|
|
21
|
+
const { done, value } = await reader.read();
|
|
22
|
+
if (done) {
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
const canContinue = outgoing.write(value);
|
|
26
|
+
if (!canContinue) {
|
|
27
|
+
await new Promise((resolve) => {
|
|
28
|
+
outgoing.once("drain", resolve);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
48
31
|
}
|
|
32
|
+
} finally {
|
|
33
|
+
reader.releaseLock();
|
|
34
|
+
}
|
|
49
35
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
try {
|
|
70
|
-
await writeBodyStream(body, outgoing);
|
|
71
|
-
outgoing.end();
|
|
72
|
-
}
|
|
73
|
-
catch (error) {
|
|
74
|
-
// 处理客户端提前断开等情况
|
|
75
|
-
if (!outgoing.destroyed) {
|
|
76
|
-
outgoing.destroy(error instanceof Error ? error : new Error(String(error)));
|
|
77
|
-
}
|
|
36
|
+
async function writeResponse(response, outgoing) {
|
|
37
|
+
outgoing.statusCode = response.status;
|
|
38
|
+
const headers = buildOutgoingHeaders(response.headers);
|
|
39
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
40
|
+
outgoing.setHeader(key, value);
|
|
41
|
+
}
|
|
42
|
+
const body = response.body;
|
|
43
|
+
if (!body) {
|
|
44
|
+
outgoing.end();
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
await writeBodyStream(body, outgoing);
|
|
49
|
+
outgoing.end();
|
|
50
|
+
} catch (error) {
|
|
51
|
+
if (!outgoing.destroyed) {
|
|
52
|
+
outgoing.destroy(
|
|
53
|
+
error instanceof Error ? error : new Error(String(error))
|
|
54
|
+
);
|
|
78
55
|
}
|
|
56
|
+
}
|
|
79
57
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
// 对于小响应,直接读取全部内容
|
|
96
|
-
const buffer = await response.arrayBuffer();
|
|
97
|
-
outgoing.end(Buffer.from(buffer));
|
|
58
|
+
async function writeResponseSimple(response, outgoing) {
|
|
59
|
+
outgoing.statusCode = response.status;
|
|
60
|
+
const headers = buildOutgoingHeaders(response.headers);
|
|
61
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
62
|
+
outgoing.setHeader(key, value);
|
|
63
|
+
}
|
|
64
|
+
const body = response.body;
|
|
65
|
+
if (!body) {
|
|
66
|
+
outgoing.end();
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const buffer = await response.arrayBuffer();
|
|
70
|
+
outgoing.end(Buffer.from(buffer));
|
|
98
71
|
}
|
|
72
|
+
export {
|
|
73
|
+
writeResponse,
|
|
74
|
+
writeResponseSimple
|
|
75
|
+
};
|
|
76
|
+
//# sourceMappingURL=response.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/node-server/response.ts"],"sourcesContent":["/**\n * 优化的 Response 写入\n * 流式写入,避免内存拷贝\n */\n\nimport type { ServerResponse } from \"node:http\";\n\n/**\n * 构建 Node.js 响应头\n * 处理 set-cookie 多值情况\n */\nfunction buildOutgoingHeaders(\n headers: Headers,\n): Record<string, string | string[]> {\n const result: Record<string, string | string[]> = {};\n const cookies: string[] = [];\n\n headers.forEach((value, key) => {\n if (key === \"set-cookie\") {\n cookies.push(value);\n } else {\n result[key] = value;\n }\n });\n\n if (cookies.length > 0) {\n result[\"set-cookie\"] = cookies;\n }\n\n return result;\n}\n\n/**\n * 流式写入 Response body 到 ServerResponse\n * 支持背压处理,避免内存溢出\n */\nasync function writeBodyStream(\n body: ReadableStream<Uint8Array>,\n outgoing: ServerResponse,\n): Promise<void> {\n const reader = body.getReader();\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n\n if (done) {\n break;\n }\n\n // 背压处理:如果写入返回 false,等待 drain 事件\n const canContinue = outgoing.write(value);\n if (!canContinue) {\n await new Promise<void>((resolve) => {\n outgoing.once(\"drain\", resolve);\n });\n }\n }\n } finally {\n reader.releaseLock();\n }\n}\n\n/**\n * 将 Web Response 写入 Node.js ServerResponse\n * 流式写入,零拷贝\n */\nexport async function writeResponse(\n response: Response,\n outgoing: ServerResponse,\n): Promise<void> {\n // 设置状态码\n outgoing.statusCode = response.status;\n\n // 设置响应头\n const headers = buildOutgoingHeaders(response.headers);\n for (const [key, value] of Object.entries(headers)) {\n outgoing.setHeader(key, value);\n }\n\n const body = response.body;\n\n // 无 body 的情况\n if (!body) {\n outgoing.end();\n return;\n }\n\n // 流式写入 body\n try {\n await writeBodyStream(body, outgoing);\n outgoing.end();\n } catch (error) {\n // 处理客户端提前断开等情况\n if (!outgoing.destroyed) {\n outgoing.destroy(\n error instanceof Error ? error : new Error(String(error)),\n );\n }\n }\n}\n\n/**\n * 简化版写入(用于已知小体积响应)\n * 直接 arrayBuffer 转换,适用于确定的小响应\n */\nexport async function writeResponseSimple(\n response: Response,\n outgoing: ServerResponse,\n): Promise<void> {\n outgoing.statusCode = response.status;\n\n const headers = buildOutgoingHeaders(response.headers);\n for (const [key, value] of Object.entries(headers)) {\n outgoing.setHeader(key, value);\n }\n\n const body = response.body;\n if (!body) {\n outgoing.end();\n return;\n }\n\n // 对于小响应,直接读取全部内容\n const buffer = await response.arrayBuffer();\n outgoing.end(Buffer.from(buffer));\n}\n"],"mappings":";AAWA,SAAS,qBACP,SACmC;AACnC,QAAM,SAA4C,CAAC;AACnD,QAAM,UAAoB,CAAC;AAE3B,UAAQ,QAAQ,CAAC,OAAO,QAAQ;AAC9B,QAAI,QAAQ,cAAc;AACxB,cAAQ,KAAK,KAAK;AAAA,IACpB,OAAO;AACL,aAAO,GAAG,IAAI;AAAA,IAChB;AAAA,EACF,CAAC;AAED,MAAI,QAAQ,SAAS,GAAG;AACtB,WAAO,YAAY,IAAI;AAAA,EACzB;AAEA,SAAO;AACT;AAMA,eAAe,gBACb,MACA,UACe;AACf,QAAM,SAAS,KAAK,UAAU;AAE9B,MAAI;AACF,WAAO,MAAM;AACX,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAE1C,UAAI,MAAM;AACR;AAAA,MACF;AAGA,YAAM,cAAc,SAAS,MAAM,KAAK;AACxC,UAAI,CAAC,aAAa;AAChB,cAAM,IAAI,QAAc,CAAC,YAAY;AACnC,mBAAS,KAAK,SAAS,OAAO;AAAA,QAChC,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF,UAAE;AACA,WAAO,YAAY;AAAA,EACrB;AACF;AAMA,eAAsB,cACpB,UACA,UACe;AAEf,WAAS,aAAa,SAAS;AAG/B,QAAM,UAAU,qBAAqB,SAAS,OAAO;AACrD,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,OAAO,GAAG;AAClD,aAAS,UAAU,KAAK,KAAK;AAAA,EAC/B;AAEA,QAAM,OAAO,SAAS;AAGtB,MAAI,CAAC,MAAM;AACT,aAAS,IAAI;AACb;AAAA,EACF;AAGA,MAAI;AACF,UAAM,gBAAgB,MAAM,QAAQ;AACpC,aAAS,IAAI;AAAA,EACf,SAAS,OAAO;AAEd,QAAI,CAAC,SAAS,WAAW;AACvB,eAAS;AAAA,QACP,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AAAA,MAC1D;AAAA,IACF;AAAA,EACF;AACF;AAMA,eAAsB,oBACpB,UACA,UACe;AACf,WAAS,aAAa,SAAS;AAE/B,QAAM,UAAU,qBAAqB,SAAS,OAAO;AACrD,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,OAAO,GAAG;AAClD,aAAS,UAAU,KAAK,KAAK;AAAA,EAC/B;AAEA,QAAM,OAAO,SAAS;AACtB,MAAI,CAAC,MAAM;AACT,aAAS,IAAI;AACb;AAAA,EACF;AAGA,QAAM,SAAS,MAAM,SAAS,YAAY;AAC1C,WAAS,IAAI,OAAO,KAAK,MAAM,CAAC;AAClC;","names":[]}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
+
import { Server } from 'node:http';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Node.js 服务器适配器
|
|
3
5
|
* 提供类似 Bun.serve 的 API
|
|
4
6
|
*/
|
|
5
|
-
|
|
7
|
+
|
|
6
8
|
/** fetch 函数类型 */
|
|
7
|
-
|
|
9
|
+
type FetchHandler = (request: Request) => Response | Promise<Response>;
|
|
8
10
|
/** serve 配置选项 */
|
|
9
|
-
|
|
11
|
+
interface ServeOptions {
|
|
10
12
|
/** fetch 处理函数 */
|
|
11
13
|
fetch: FetchHandler;
|
|
12
14
|
/** 端口号,默认 3000 */
|
|
@@ -17,9 +19,9 @@ export interface ServeOptions {
|
|
|
17
19
|
onError?: (error: Error) => Response | Promise<Response>;
|
|
18
20
|
}
|
|
19
21
|
/** serve 返回的服务器信息 */
|
|
20
|
-
|
|
22
|
+
interface ServeResult {
|
|
21
23
|
/** Node.js HTTP Server 实例 */
|
|
22
|
-
server:
|
|
24
|
+
server: Server;
|
|
23
25
|
/** 服务器端口 */
|
|
24
26
|
port: number;
|
|
25
27
|
/** 服务器主机名 */
|
|
@@ -44,9 +46,11 @@ export interface ServeResult {
|
|
|
44
46
|
* });
|
|
45
47
|
* ```
|
|
46
48
|
*/
|
|
47
|
-
|
|
49
|
+
declare function serve(options: ServeOptions, callback?: () => void): ServeResult;
|
|
48
50
|
/**
|
|
49
51
|
* 创建适配器服务器(不自动启动)
|
|
50
52
|
* 用于需要更多控制的场景
|
|
51
53
|
*/
|
|
52
|
-
|
|
54
|
+
declare function createAdaptorServer(fetch: FetchHandler, onError?: (error: Error) => Response | Promise<Response>): Server;
|
|
55
|
+
|
|
56
|
+
export { type FetchHandler, type ServeOptions, type ServeResult, createAdaptorServer, serve };
|