dynapm 1.0.13 → 1.0.15

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/CHANGELOG.md CHANGED
@@ -5,26 +5,85 @@
5
5
  格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.0.0/),
6
6
  版本号遵循 [语义化版本](https://semver.org/lang/zh-CN/)。
7
7
 
8
+ ## [1.0.15] - 2026-03-22
9
+
10
+ ### 🚀 性能优化
11
+ - **`typeof` 替代 `Array.isArray`**: 响应头转发中 4 处 `Array.isArray(value)` 替换为 `typeof value === 'string'`,V8 内置类型检查比原型链遍历快 41%
12
+ - **`getCaseSensitiveMethod()` 消除热路径 `toUpperCase()`**: uWS `getMethod()` 返回小写方法名,改为直接使用 `getCaseSensitiveMethod()` 获取原始大小写
13
+ - **404 路径提前返回**: `handleRequest` 中 hostname 查找提前到 header 收集之前,404 请求跳过不必要的 CPU 和内存开销
14
+ - **CRLF 快速路径**: 热路径中用 `includes('\r') || includes('\n')` 快速检查跳过正则替换
15
+ - **移除 node-fetch 依赖**: 使用 Node.js 22 内置 `fetch` API
16
+ - **预计算 targetPort**: RouteMapping 中缓存目标端口,避免每次 `parseInt`
17
+
18
+ ### 🔴 Bug 修复
19
+ - **activeConnections 双重递减**: cleanup() 添加 `cleaned` 守卫防止多次触发
20
+ - **代理请求 timeout 未处理**: proxyReq 监听 `timeout` 事件并 `destroy()`
21
+ - **502 vs 504 区分**: 代理请求超时返回 504 Gateway Timeout,连接错误返回 502
22
+ - **startService fire-and-forget 竞态**: `serviceManager.start()` 改为 `await`,避免端口短暂可用时错误标记为 online
23
+ - **WebSocket handler 无条件日志修复**: `open` 回调中的 JSON.stringify 日志添加 `enableWebSocketLog` 守卫
24
+ - **test-startup-recovery 闲置超时测试修复**: 等待时间从 14s 增加到 16s,修复时序敏感测试偶发失败
25
+
26
+ ### ✅ 代码质量
27
+ - **消除所有 `any` 类型**: `test-all.ts`、`test-proxy-comprehensive.ts`、`test-gateway-robustness.ts`、`test-pilot.ts`、`command-executor.ts` 中的 `any` 替换为 `unknown` + `instanceof` 类型守卫
28
+ - **Admin API `method.toLowerCase()` 移除**: uWS `getMethod()` 返回小写方法名,5 处冗余 `toLowerCase()` 已移除
29
+ - **Admin API `findServiceMapping` O(n) → O(1)**: 懒初始化 `serviceName → RouteMapping` 索引 Map
30
+ - **`getServicesList` 消除重复遍历**: 使用预构建的服务名称索引 Map
31
+ - **health-checker.ts 消除循环内 `new URL()`**: 预解析 URL 对象,传入 `host`/`port` 参数
32
+ - **`Buffer.alloc` → `Buffer.allocUnsafe`**: `collectRequestBody` 和 `handleDirectProxy` 中使用 `allocUnsafe` 跳过清零
33
+
34
+ ### 🧪 测试(224 个用例全部通过,22 个测试套件)
35
+ - 新增 test-gateway-resilience.ts: 8 个网关韧性与边界深度测试
36
+ - 新增 test-crlf-fastpath.ts: 11 个 CRLF 安全性验证测试
37
+ - 新增 test-gzip-passthrough.ts: 5 个 Gzip 压缩响应透传测试
38
+ - 新增 test-startservice-race.ts: 6 个 startService 竞态条件测试
39
+ - 新增 test-port-ws-proxy.ts: 10 个端口绑定 WebSocket 代理测试
40
+ - 新增 test-admin-api-deep.ts: 10 个管理 API 深度测试
41
+ - 新增 test-gateway-boundary.ts: 10 个网关边界与安全测试
42
+ - 新增 test-proxy-deep.ts: 10 个代理深度与资源管理测试
43
+ - 新增 test-proxy-edge-paths.ts: 10 个代理边缘路径测试
44
+ - 新增 test-concurrent-post-body.ts: 10 个并发与竞争条件测试
45
+ - 新增 test-proxy-supplementary.ts: 10 个代理场景补充测试
46
+ - 新增 test-ws-concurrent.ts: 10 个 WebSocket 并发与稳定性测试
47
+
48
+ ## [1.0.14] - 2026-03-20
49
+
50
+ ### 🔴 Bug 修复
51
+ - **按需启动 POST 请求体丢失(严重)**: uWS 的 onData 回调中 ArrayBuffer 是借用语义,`Buffer.from(ab)` 底层数据被后续回调覆盖。改用 `Buffer.alloc + copy` 确保数据复制
52
+ - **并发按需启动返回 502**: 多个请求同时到达离线服务时,只有第一个触发启动,其他请求等待启动完成后再代理
53
+ - **transfer-encoding 头冲突**: forwardProxyRequest 中过滤 transfer-encoding 头,避免与 content-length 冲突导致后端 400
54
+ - **后端崩溃自动恢复**: 检测到后端不可达(ECONNREFUSED)时,自动将非 proxyOnly 服务状态重置为 offline
55
+ - **端口路由并发启动**: handlePortBindingRequest 补全 starting/stopping 状态处理,与 hostname 路由保持一致
56
+
57
+ ### 🔒 安全加固
58
+ - 请求体大小限制 10MB,防止 DoS 攻击
59
+ - WebSocket 消息队列限制 1000 条,防止内存泄漏
60
+ - CRLF 注入防护:请求头值中的 `\r\n` 被清理
61
+ - 端口路由 WebSocket close handler 补充后端连接清理
62
+
63
+ ### 🚀 性能优化
64
+ - **去除 undici,恢复原生 http 模块**: 吞吐量从 4,523 提升至 **5,942 req/s(+31%)**,延迟从 10.6ms 降至 **10.3ms**
65
+ - 预编译 CRLF 正则,避免热路径重复创建
66
+ - Set 替代内联条件判断,优化请求头跳过逻辑
67
+
68
+ ### 🧪 测试(81 个用例全部通过)
69
+ - test-proxy-comprehensive.ts: 23 个综合代理测试
70
+ - test-edge-cases.ts: 15 个极端场景测试
71
+ - test-gateway-robustness.ts: 13 个健壮性测试
72
+ - test-admin-api-lifecycle.ts: 12 个管理 API 生命周期测试
73
+ - test-port-route-start.ts: 9 个端口路由按需启动测试
74
+ - test-security-stability.ts: 9 个安全与稳定性深度测试
75
+
76
+ ---
77
+
8
78
  ## [1.0.13] - 2026-02-10
9
79
 
10
80
  ### 🚀 性能优化
11
- - **重大性能提升**:使用 undici 替代原生 http 模块作为 HTTP 客户端
12
- - 吞吐量提升 **28.2%**:4345 → 5571 req/s
13
- - 延迟保持 11.4ms(无退化)
14
- - 使用 `undici.request()` API 实现流式转发
15
- - 避免了 `undici.stream()` + Writable stream 的包装开销
81
+ - 使用 undici 替代原生 http 模块(已在 v1.0.14 回退,原生 http 性能更优)
16
82
 
17
83
  ### 🔧 改进
18
- - 移除不再使用的 http/https 模块相关代码
19
- - 清理 RouteMapping 中的冗余字段(isHttps、httpModule、httpAgent)
84
+ - 清理 RouteMapping 中的冗余字段
20
85
  - 代码更简洁,维护性更好
21
86
 
22
- ### 📚 技术细节
23
- - undici 的 `request()` API 比 `stream()` API 更适合代理场景
24
- - `stream()` 适用于消费响应(写入文件、解析 JSON)
25
- - `request()` 返回 Readable stream,可以手动控制流式转发
26
- - 完全保持流式处理,客户端延迟无增加
27
-
28
87
  ---
29
88
 
30
89
  ## [1.0.12] - 2026-02-10
package/CLAUDE.md CHANGED
@@ -1,21 +1,20 @@
1
1
  # DynaPM - Claude Code 项目配置
2
2
 
3
- DynaPM 是一个智能网关,通过按需启动和闲置自动停止的方式,帮助用户在资源受限的服务器上管理数百个低频访问的服务。
3
+ DynaPM 是一个智能网关(类似nginx)/进程管理工具(类似pm2),通过按需启动(请求到达时通过查找配置判断请求属于哪个程序,然后网关转发请求,当程序还未启动会执行启动命令等待就绪后再实际转发)和闲置自动停止的方式,帮助用户在资源受限的服务器上运行成千上万个低频访问+少量高频访问的服务。
4
4
 
5
5
  **核心特性:**
6
- - ⚡ 极速冷启动(开销仅 25ms)
7
- - 🚀 流式代理(1-2ms 延迟)
6
+ - ⚡ 极速冷启动
7
+ - 🚀 双向流式转发代理实现极低的请求延迟:将请求体流式给代理服务,将代理服务的响应流式给请求者 所以不需要缓冲请求或者响应,唯一的需要缓冲的时机就是请求到达网关,但是需要被网关唤起的程序还没有启动成功的时候
8
8
  - 🌐 支持 SSE 和 WebSocket
9
- - 🎛️ 通用服务管理(可替代PM2、Docker、systemd 等)
10
- - 🔄 闲置自动回收
9
+ - 🎛️ 基于bash的通用服务管理(可用于管理PM2、Docker、systemd 等任意服务)
10
+ - 🔄 闲置自动回收资源
11
11
 
12
12
  ## 技术栈
13
13
 
14
14
  - **运行时**: Node.js 22+
15
- - **Web 框架**: uWebSockets.js(性能比 Fastify 快 10 倍以上)
16
- - **日志**: Pino(异步结构化日志)
15
+ - **Web 框架**: uWebSockets.js(最佳性能)
16
+ - **日志**: Pino
17
17
  - **配置**: c12(支持 TypeScript)
18
- - **构建**: rslib
19
18
  - **包管理**: pnpm
20
19
  - **测试**: tsx + 自定义测试套件
21
20
 
@@ -37,8 +36,6 @@ DynaPM/
37
36
  │ ├── test-all.ts # 完整测试套件(12个测试)
38
37
  │ ├── server-*.ts # 测试服务器
39
38
  │ └── benchmark.js # 性能测试
40
- ├── docs/
41
- │ └── NPM_OIDC_SETUP.md # npm OIDC 发布配置指南
42
39
  ├── .github/workflows/
43
40
  │ └── release.yml # 自动发布到 npm
44
41
  ├── CHANGELOG.md # 版本更新日志
@@ -49,12 +46,7 @@ DynaPM/
49
46
 
50
47
  ## 开发指南
51
48
 
52
- ### 快速开始
53
-
54
49
  ```bash
55
- # 安装依赖
56
- pnpm install
57
-
58
50
  # 运行测试
59
51
  pnpm test
60
52
 
@@ -67,4 +59,4 @@ pnpm benchmark
67
59
 
68
60
  ### 发布新版本
69
61
 
70
- 流程 : CHANGELOG → commit npm version (git tag) → push
62
+ 流程 : CHANGELOG → commit →更新 npm version (git add tag) →git push (github actions 会通过 oicd 发包 npm )
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  > **Dynamic Process Manager** - A lightweight, universal service management system with serverless-like features.
6
6
 
7
- [![npm version](https://badge.fury.io/js/dynapm.svg)](https://www.npmjs.com/package/dynapm) ![Tests](https://img.shields.io/badge/tests-12%2F12%20passing-green) ![Performance](https://img.shields.io/badge/overhead-25ms-brightgreen)
7
+ [![npm version](https://badge.fury.io/js/dynapm.svg)](https://www.npmjs.com/package/dynapm) ![Tests](https://img.shields.io/badge/tests-81%2F81%20passing-green) ![Performance](https://img.shields.io/badge/overhead-25ms-brightgreen)
8
8
 
9
9
  DynaPM is a **lightweight alternative** to complex container orchestration platforms (like Knative, Sablier) for private deployments. It helps you manage hundreds of low-frequency services on resource-constrained servers by starting them on-demand and stopping them when idle.
10
10
 
@@ -57,7 +57,7 @@ You have many side projects or internal tools that:
57
57
 
58
58
  - **DynaPM overhead**: Only **25ms** (startup command: 8ms + port wait: 17ms)
59
59
  - **Instant retry**: Zero-delay polling, forward immediately when port is ready
60
- - **Total cold start**: ~500ms (including service boot time, e.g., ~475ms for Node.js apps)
60
+ - **Total cold start**: ~185ms (including service boot time, e.g., ~160ms for Node.js apps)
61
61
 
62
62
  ### 🚀 **Stream Proxying**
63
63
 
@@ -147,9 +147,9 @@ Configure ANY service using bash commands - no limits:
147
147
  ```
148
148
  Test Environment: Node.js HTTP Server (autocannon benchmark)
149
149
 
150
- ✅ Cold start: ~48ms (DynaPM: 25ms + service boot: 23ms)
151
- ✅ Stream proxy: Avg 9.5ms (range: 8-14ms)
152
- ✅ Throughput: 8,383 req/s (multi-service, 60 concurrent)
150
+ ✅ Cold start: ~185ms (DynaPM: 25ms + service boot: 160ms)
151
+ ✅ Stream proxy: Avg 10.3ms (range: 9-12ms)
152
+ ✅ Throughput: 5,942 req/s (multi-service, 150 concurrent)
153
153
  ✅ Load test: Low latency even under high concurrency
154
154
  ✅ Memory overhead: ~50MB (Node.js runtime)
155
155
  ✅ Bundle size: 21.7KB (minified)
@@ -245,7 +245,7 @@ pnpm test
245
245
 
246
246
  ### Test Coverage
247
247
 
248
- The automated tests validate 12 core functionalities:
248
+ The automated tests validate 81 test cases across 6 test suites:
249
249
 
250
250
  1. ✅ **On-demand start** - Services auto-start when offline
251
251
  2. ✅ **Hot start** - Direct proxy when service is running
@@ -259,6 +259,9 @@ The automated tests validate 12 core functionalities:
259
259
  10. ✅ **SSE streaming** - Server-Sent Events proxy support
260
260
  11. ✅ **WebSocket** - WebSocket bidirectional communication support
261
261
  12. ✅ **Long connections** - Active connections prevent premature shutdown
262
+ 13. ✅ **Concurrent startup** - Multiple requests to offline service
263
+ 14. ✅ **Security hardening** - Body size limits, CRLF injection protection
264
+ 15. ✅ **Port routing** - Direct port-based proxy and on-demand start
262
265
 
263
266
  ### Test Output Example
264
267
 
@@ -426,8 +429,8 @@ Test: Total time from offline to first accessible request
426
429
 
427
430
  Results:
428
431
  ├─ DynaPM overhead: 25ms (startup command: 8ms + TCP port wait: 17ms)
429
- ├─ Service boot: 17ms (Node.js application)
430
- └─ Total cold start: 42ms
432
+ ├─ Service boot: 160ms (Node.js application)
433
+ └─ Total cold start: 185ms
431
434
  ```
432
435
 
433
436
  ### Stream Proxy Performance
@@ -436,30 +439,23 @@ Results:
436
439
  Test: Single request latency when service is running
437
440
 
438
441
  Results:
439
- ├─ Average latency: 9.3ms
440
- ├─ Min latency: 8ms
442
+ ├─ Average latency: 10.3ms
443
+ ├─ Min latency: 9ms
441
444
  ├─ Max latency: 12ms
442
- └─ Latency range: 8-12ms
445
+ └─ Latency range: 9-12ms
443
446
  ```
444
447
 
445
448
  ### Throughput Performance
446
449
 
447
450
  ```
448
- Test: Multi-service benchmark (3 services × 20 concurrent, 5 seconds)
451
+ Test: Multi-service benchmark (3 services × 50 concurrent, 5 seconds)
449
452
 
450
453
  Results:
451
- ├─ Total requests: 42,000 requests
452
- ├─ Average throughput: 8,383 req/s
453
- ├─ Per-service: 2,794 req/s
454
+ ├─ Total requests: 29,710 requests
455
+ ├─ Average throughput: 5,942 req/s
456
+ ├─ Per-service: ~1,980 req/s
454
457
  ├─ Errors: 0
455
458
  └─ Test duration: 5 seconds
456
-
457
- Test: Single service benchmark (50 concurrent, 5 seconds)
458
-
459
- Results:
460
- ├─ Requests/sec: 4,225+ req/s
461
- ├─ Average latency: ~23ms
462
- └─ Total requests: 21k requests
463
459
  ```
464
460
 
465
461
  ### Resource Usage
package/README_zh.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  > **动态进程管理器** - 具有类 serverless 特性的轻量级通用服务管理系统
6
6
 
7
- [![npm version](https://badge.fury.io/js/dynapm.svg)](https://www.npmjs.com/package/dynapm) ![Tests](https://img.shields.io/badge/tests-12%2F12%20passing-green) ![Performance](https://img.shields.io/badge/overhead-25ms-brightgreen)
7
+ [![npm version](https://badge.fury.io/js/dynapm.svg)](https://www.npmjs.com/package/dynapm) ![Tests](https://img.shields.io/badge/tests-81%2F81%20passing-green) ![Performance](https://img.shields.io/badge/overhead-25ms-brightgreen)
8
8
 
9
9
  DynaPM 是**复杂容器编排平台(如 Knative、Sablier)的轻量级替代方案**,专为私有化部署设计。它通过按需启动和闲置自动停止的方式,帮助你在资源受限的服务器上管理数百个低频访问的服务。
10
10
 
@@ -57,7 +57,7 @@ DynaPM 是**复杂容器编排平台(如 Knative、Sablier)的轻量级替
57
57
 
58
58
  - **DynaPM 开销**:仅 **25ms**(启动命令 8ms + 端口等待 17ms)
59
59
  - **失败立即重试**:无延迟轮询,端口可用即刻转发
60
- - **总冷启动**:~500ms(包括服务本身启动时间,如 Node.js 应用 ~475ms
60
+ - **总冷启动**:~185ms(包括服务本身启动时间,如 Node.js 应用 ~160ms
61
61
 
62
62
  ### 🚀 **流式代理**
63
63
 
@@ -146,9 +146,9 @@ DynaPM 原生支持现代实时通信协议:
146
146
  ```
147
147
  测试环境:Node.js HTTP 服务器 (autocannon 压测)
148
148
 
149
- ✅ 冷启动时间: ~48ms (DynaPM: 25ms + 服务启动: 23ms)
150
- ✅ 流式代理延迟: 平均 9.5ms (范围: 8-14ms)
151
- ✅ 吞吐量: 8,383 req/s (多服务, 60 并发)
149
+ ✅ 冷启动时间: ~185ms (DynaPM: 25ms + 服务启动: 160ms)
150
+ ✅ 流式代理延迟: 平均 10.3ms (范围: 9-12ms)
151
+ ✅ 吞吐量: 5,942 req/s (多服务, 150 并发)
152
152
  ✅ 压测延迟: 高并发下保持低延迟
153
153
  ✅ 内存开销: ~50MB (Node.js 运行时)
154
154
  ✅ 代码体积: 21.7KB (压缩后)
@@ -244,7 +244,7 @@ pnpm test
244
244
 
245
245
  ### 测试覆盖场景
246
246
 
247
- 自动化测试会验证以下 12 个核心功能:
247
+ 自动化测试会验证以下 81 个测试用例(6 个测试套件):
248
248
 
249
249
  1. ✅ **按需启动** - 服务离线时自动启动
250
250
  2. ✅ **热启动** - 服务运行时直接代理,无需重新启动
@@ -258,6 +258,9 @@ pnpm test
258
258
  10. ✅ **SSE 流式传输** - Server-Sent Events 代理支持
259
259
  11. ✅ **WebSocket** - WebSocket 双向通信支持
260
260
  12. ✅ **长连接代理** - 活跃连接阻止服务被提前关闭
261
+ 13. ✅ **并发启动** - 多个请求同时到达离线服务
262
+ 14. ✅ **安全加固** - 请求体大小限制、CRLF 注入防护
263
+ 15. ✅ **端口路由** - 端口直连代理和按需启动
261
264
 
262
265
  ### 测试输出示例
263
266
 
@@ -424,8 +427,8 @@ npm install -g autocannon
424
427
 
425
428
  结果:
426
429
  ├─ DynaPM 开销: 25ms (启动命令 8ms + TCP 端口等待 17ms)
427
- ├─ 服务启动时间: 17ms (Node.js 应用)
428
- └─ 总冷启动时间: 42ms
430
+ ├─ 服务启动时间: 160ms (Node.js 应用)
431
+ └─ 总冷启动时间: 185ms
429
432
  ```
430
433
 
431
434
  ### 流式代理性能
@@ -434,22 +437,22 @@ npm install -g autocannon
434
437
  测试:服务运行时的单次请求延迟
435
438
 
436
439
  结果:
437
- ├─ 平均延迟: 9.3ms
438
- ├─ 最小延迟: 8ms
440
+ ├─ 平均延迟: 10.3ms
441
+ ├─ 最小延迟: 9ms
439
442
  ├─ 最大延迟: 12ms
440
- └─ 延迟范围: 8-12ms
443
+ └─ 延迟范围: 9-12ms
441
444
  ```
442
445
 
443
446
  ### 吞吐量性能
444
447
 
445
448
  ```
446
- 测试:autocannon 压测 (100 并发, 10 秒)
449
+ 测试:多服务混合压测 (3 服务 × 50 并发, 5 秒)
447
450
 
448
451
  结果:
449
- ├─ 请求数/秒: 4,225 req/s
450
- ├─ 平均延迟: 23.16ms
451
- ├─ 总请求数: 42k requests
452
- └─ 测试时长: 10
452
+ ├─ 请求数/秒: 5,942 req/s
453
+ ├─ 平均延迟: ~10ms
454
+ ├─ 总请求数: 29,710 requests
455
+ └─ 测试时长: 5
453
456
  ```
454
457
 
455
458
  ### 资源占用
package/TASK.md ADDED
@@ -0,0 +1,271 @@
1
+ 具有类 serverless 特性的轻量级通用服务管理系统:dynapm
2
+ ## dynapm 开发
3
+
4
+ /loop 先检查 TASK.md 中是否有未完成的任务请逐项完成并在充分test验证再继续下一项,如果没有则请请完善当前项目:监测并优化程序性能,修改完毕后需要进行实际运行测试,请自我完善,不要询问我任何事情,也不要切换其他模式(例如 plan mode)
5
+ 作为网关的测试一定要非常严谨,测试各种可能的情况以及极端情况。
6
+ 所有文件使用 ts,需要临时运行的使用 node --experimental-strip-types -e xxx.ts 来执行
7
+ 这一次主要考虑性能,要在不破坏所有功能的前提下优化性能,但是不要为了优化而优化,必须经过仔细的评估,不要无脑上缓存,缓存很容易出bug,否则可读性更强。然后咱们的网关可能已经到达了一般情况下的上限,所以你可能需要去互联网上查找node的一些大神使用的技巧
8
+
9
+ ## TASKS
10
+
11
+ [x] 请在各个层面完善一下 serveless host 这个功能,尤其是前端,太low了,至少也得有 https://www.typescriptlang.org/play/ 这种水准的编辑和运行体验吧
12
+ [x] 充分测试当前的代理功能是否正确
13
+ [x] 创建一个实用的dynam能力演示程序:实现一个运行ts/js的 serveless host(并不属于 dynapm,但是可以被 dynapm 运行,然后请求又可以被这个 serveless host 路由到 对应的 ts文件去执行):支持用户通过网站访问并编写 ts 上传执行和测试执行
14
+
15
+ ## 已完成的工作
16
+
17
+ ### 2026-03-20
18
+
19
+ #### 网关 Bug 修复
20
+ - **并发按需启动修复**: 多个请求同时到达离线服务时,只有第一个触发启动,其他请求等待启动完成后再代理(之前返回 502)
21
+ - **后端崩溃自动恢复**: 当 handleDirectProxy 检测到后端不可达(ECONNREFUSED),自动将非 proxyOnly 服务状态重置为 offline,后续请求可重新触发按需启动
22
+ - **端口路由并发启动修复**: handlePortBindingRequest 补全 starting/stopping 状态处理,与 hostname 路由保持一致
23
+ - **echo-server 支持命令行端口参数**: `parseInt(process.argv[2] || '3099')`,允许不同测试配置使用不同端口
24
+ - **按需启动 POST 请求体丢失修复(严重)**: uWS 的 onData 回调中 ArrayBuffer 是借用语义,`Buffer.from(ab)` 底层数据被后续回调覆盖。改用 `Buffer.alloc + copy` 确保数据复制
25
+ - **transfer-encoding 头冲突修复**: forwardProxyRequest 中过滤 transfer-encoding 头,避免与 content-length 冲突导致后端 400
26
+ - **请求体大小限制(10MB)**: collectRequestBody 超过限制时截断,防止 DoS 攻击
27
+ - **WebSocket 消息队列限制(1000)**: 防止后端未连接时消息无限堆积导致内存泄漏
28
+ - **端口路由 WebSocket close 清理**: 端口路由的 close handler 补充后端 WebSocket 关闭逻辑
29
+
30
+ #### 性能优化
31
+ - **预编译 CRLF 正则**: `GatewayConstants.CRLF_REGEX` 避免热路径中重复创建正则对象
32
+ - **Set 替代内联条件**: `GatewayConstants.SKIP_REQUEST_HEADERS` 使用 Set.has() 替代重复 toLowerCase + 条件判断
33
+ - **预计算 targetPort**: RouteMapping 中缓存目标端口,避免热路径中 parseInt 解析
34
+
35
+ #### 网关稳定性修复
36
+ - **activeConnections 双重递减修复**: handleDirectProxy 和 forwardProxyRequest 中 cleanup() 添加 `cleaned` 守卫,防止 onAborted/proxyReq error/proxyRes end 多次触发导致 activeConnections 变为负数,进而导致闲置超时永远不触发
37
+ - **代理请求超时处理**: proxyReq 添加 `timeout` 事件监听,超时后调用 `destroy()` 触发 error 事件正确返回 502。之前 timeout 事件未被处理,导致后端慢响应时客户端无限等待
38
+
39
+ #### 测试覆盖(224 个测试全部通过)
40
+ - **test-proxy-comprehensive.ts**: 23 个综合代理测试
41
+ - **test-advanced-proxy.ts**: 12 个高级代理场景测试(PUT/PATCH/DELETE 请求体转发、HEAD 无响应体、OPTIONS CORS、空 POST、根路径、查询参数特殊字符、30 个自定义头、Host 头覆盖、流式响应、快速连续请求、活跃服务闲置测试、WS+HTTP 并发)
42
+ - **test-edge-cases.ts**: 15 个极端场景测试
43
+ - **test-gateway-robustness.ts**: 13 个健壮性测试
44
+ - **test-admin-api-lifecycle.ts**: 12 个管理 API 生命周期测试
45
+ - **test-admin-api-deep.ts**: 10 个管理 API 深度与网关边界测试(新增)
46
+ - 管理 API 事件流 (SSE)
47
+ - 管理 API 路由边界(PUT/DELETE 404、路径遍历、不存在 API)
48
+ - 请求体超过 10MB 截断(按需启动路径)
49
+ - 3xx 重定向 Location 头透传
50
+ - 50 个并发请求同时断开
51
+ - 服务按需启动超时行为
52
+ - 非 JSON Content-Type POST
53
+ - 管理 API 并发请求 (40个)
54
+ - OPTIONS 预检请求
55
+ - 网关直接访问返回 404
56
+ - **test-gateway-boundary.ts**: 10 个网关边界与安全深度测试(新增)
57
+ - CRLF 注入防护验证
58
+ - 并发按需启动竞争 (20个)
59
+ - 大响应体流式转发 (1MB)
60
+ - URL 特殊字符透传(中文、编码)
61
+ - 超长请求头值 (16KB)
62
+ - 响应头大小写兼容
63
+ - 重复请求头处理
64
+ - 快速连续请求到不同路径
65
+ - 连接超时后网关稳定性
66
+ - 多服务并发代理 (20个)
67
+ - **test-proxy-deep.ts**: 10 个代理深度与资源管理测试(新增)
68
+ - 慢响应时客户端断开 activeConnections 准确性(含闲置超时验证)
69
+ - stopping 状态下收到请求(等待停止完成后启动)
70
+ - WebSocket 消息队列溢出 (1200条)
71
+ - PATCH/PUT 请求体转发完整性
72
+ - 分块传输响应体转发
73
+ - 带查询参数的 POST 请求
74
+ - 多次快速启停状态一致性 (5轮)
75
+ - 长连接 keep-alive 稳定性 (100个)
76
+ - 后端 500 错误网关不崩溃
77
+ - 50 个错误请求后网关稳定性
78
+ - **test-proxy-edge-paths.ts**: 10 个代理边缘路径与错误恢复测试(新增)
79
+ - 后端响应超时处理
80
+ - 服务启动失败后重试
81
+ - 后端立即关闭连接
82
+ - 大量 502 后网关恢复 (30个)
83
+ - 服务正在启动时收到请求 (5个)
84
+ - 二进制请求体传输
85
+ - 根路径请求
86
+ - 特殊编码 URL 路径
87
+ - 服务详情字段完整性
88
+ - 网关端口扫描防护 (100个)
89
+ - **test-concurrent-post-body.ts**: 10 个并发与竞争条件测试
90
+ - **test-port-route-start.ts**: 9 个端口路由按需启动测试
91
+ - **test-security-stability.ts**: 9 个安全与稳定性深度测试
92
+ - **test-startup-recovery.ts**: 7 个服务启动失败恢复测试
93
+ - **test-proxy-supplementary.ts**: 10 个代理场景补充测试
94
+ - Set-Cookie 响应头转发
95
+ - 自定义响应头透传(X-Custom-Response、X-Rate-Limit、Cache-Control)
96
+ - 204 No Content 响应
97
+ - 分块传输响应
98
+ - GET 请求不应有 body
99
+ - Content-Type 多样性(json/plain/octet-stream)
100
+ - 并发连接后网关不崩溃
101
+ - 非 ASCII 响应体
102
+ - 快速连续启停后代理正常
103
+ - **test-pilot.ts**: 16 个 Pilot 实际运行测试(使用 dynapm.config.ts 生产配置)
104
+ - **test-ws-concurrent.ts**: 10 个 WebSocket 并发与稳定性测试(新增)
105
+ - **test-gateway-resilience.ts**: 8 个网关韧性与边界深度测试(新增)
106
+ - 20 个并发 WebSocket 连接
107
+ - 10 个并发 WebSocket ping/pong
108
+ - WebSocket 较大消息传输 (10KB)
109
+ - WebSocket 二进制消息传输
110
+ - 多连接消息顺序保证 (10条)
111
+ - 快速连接/断开循环 (30次)
112
+ - 服务停止后连接清理
113
+ - WebSocket + HTTP 混合并发
114
+ - WebSocket 活跃连接阻止闲置停止
115
+ - WebSocket 按需启动
116
+ - **test-post-body-fix.ts**: 12 个 POST 请求体完整性测试(已整合到 test-concurrent-post-body.ts)
117
+
118
+ #### echo-server 修复
119
+ - **HEAD 请求不返回 body**: 包装 res.end 使 HEAD 请求忽略 data 参数,修复 node:http 客户端 HTTP 解析错误
120
+ - **3xx 重定向 Location 头**: handleStatus 端点在 3xx 状态码时返回 Location 头
121
+
122
+ #### server-ws.ts 修复
123
+ - **WebSocket isBinary 参数错误**: `ws.send(JSON.stringify(...), true, false)` 中 `isBinary=true` 传入 string 导致连接状态异常。移除多余的 `true, false` 参数,使用 uWS 默认值
124
+
125
+ #### 代码质量优化(第十三轮 2026-03-22)
126
+ - **`Array.isArray` → `typeof` 优化**: 网关响应头转发中 4 处 `Array.isArray(value) ? value.join(', ') : value` 替换为 `typeof value === 'string' ? value : value.join(', ')`。微基准验证 `typeof` 比 `Array.isArray` 快 41.2%(10ms vs 17ms,500 万次迭代),因为 `typeof` 是 V8 内置类型检查,无需遍历原型链
127
+ - **V8 微基准全面验证**: 系统性测试了 ProxyState 对象创建(1ns/op)、headers 迭代(for...in 最优,比 Object.keys 快 43.8%)、hostname 提取(substring vs slice 差异 0.1ns/req)、http.request options 创建(1.5ns/op)。结论:当前所有热路径写法已是 V8 最优
128
+ - **test-startup-recovery.ts 闲置超时等待修复**: 等待时间从 14s 增加到 16s(10s idleTimeout + 3s 检查间隔 + 3s 停止执行 buffer),修复时序敏感测试偶发失败
129
+ - **224 个测试全部通过**(22 个测试套件),基准测试 5,368 req/s(wrk -t4 -c50 -d10s),性能无退化
130
+
131
+ #### 代码质量优化(第十二轮 2026-03-22)
132
+ - **消除 `any` 类型**: 修复 `test-all.ts`、`test-proxy-comprehensive.ts`、`test-gateway-robustness.ts`、`test-pilot.ts`、`command-executor.ts` 中的 `any` 类型,替换为 `unknown` + `instanceof` 类型守卫或具体接口类型(`{ name?: string }`)
133
+ - **`for...in` vs `Object.keys()` 微基准验证**: 100 万次迭代测试显示 `Object.keys()` 比 `for...in` 慢 43.8%(391ms vs 272ms),确认当前 `for...in` 写法是最优选择,不做替换
134
+ - **互联网调研 Node.js 性能技巧**: 研究了 Node.js 22+ HTTP Agent 调优(`agentKeepAliveTimeoutBuffer`、`maxSockets`、`scheduling`)、DNS 缓存(`cacheable-lookup`)、V8 Maglev 编译器友好代码模式、`Buffer.allocUnsafeSlow` 等。结论:自定义 HTTP Agent 已在第五轮测试中验证(QPS 下降 14.6%),DNS 直连对 `127.0.0.1` 无意义(已是 IP),`for...in` 已是最优
135
+ - **224 个测试全部通过**(22 个测试套件),基准测试 5,193 req/s(wrk -t4 -c50 -d10s),性能无退化
136
+
137
+ #### 代码质量与性能优化(第十一轮 2026-03-22)
138
+ - **404 路径提前返回优化**: `handleRequest` 中将 `hostnameRoutes.get(hostname)` 检查提前到 `req.forEach` header 收集之前。对 404 请求(未知 hostname)跳过 header 遍历和 `Record<string, string>` 对象分配,减少不必要的 CPU 和内存开销
139
+ - **212 个测试全部通过**(21 个测试套件),基准测试 5,132 req/s(wrk -t4 -c50 -d10s),性能无退化
140
+
141
+ #### 代码质量与性能优化(第十轮 2026-03-22)
142
+ - **`getMethod()` → `getCaseSensitiveMethod()` 消除热路径 `toUpperCase()`**: uWS 的 `getMethod()` 返回小写方法名(如 `get`),传给 `http.request()` 前需要 `toUpperCase()` 转为大写。改为直接使用 `getCaseSensitiveMethod()` 获取原始大小写方法名(如 `GET`),消除 `handleRequest`、`handlePortBindingRequest` 入口处和 `handleDirectProxy`、`forwardProxyRequest` 中共 2 处 `toUpperCase()` 调用
143
+ - **test-crlf-fastpath.ts `rawTcpRequestBytes` EPIPE 修复**: 原实现在连接回调中同步写入所有 buffer 后才注册 error handler。当 uWS 拒绝畸形请求并关闭连接时,后续 `socket.write()` 触发 `EPIPE`。改为先注册 error handler,将 EPIPE 视为正常响应(服务端关闭连接),并在写入前检查 `socket.destroyed`
144
+ - **212 个测试全部通过**(21 个测试套件),基准测试 5,132 req/s(wrk -t4 -c50 -d10s),性能无退化
145
+
146
+ #### 代码质量与性能优化(第九轮 2026-03-22)
147
+ - **test-startup-recovery.ts `ensureEchoOffline` 测试 bug 修复**: 当服务已经是 offline 时,原代码发请求尝试重置状态,但反而触发了按需启动。改为先通过 admin API 查询服务状态,仅在 online/stopping 时才发请求触发 ECONNREFUSED 重置
148
+ - **移除未使用的 `getTargetHostPort` 辅助函数**: gateway.ts 中的 `getTargetHostPort` 已被内联为直接属性访问 `mapping.targetUrl!.hostname` 和 `mapping.targetPort`,删除未使用的函数定义
149
+ - **全量回归测试 212 个用例全部通过**(21 个测试套件顺序运行)
150
+ - **基准测试验证**: 5,347 req/s(wrk -t4 -c50 -d10s),微基准 P50 纯代理开销 0.286ms,与之前基准一致无退化
151
+ - **性能优化调研结论**: 经过互联网调研(uWS 最佳实践、Node.js 22+ 网络优化、V8 引擎优化)和代码审查,确认所有已知的 JS 层优化已实施,网关已到达 HTTP 协议双重解析的理论极限。剩余可能的优化(highWaterMark 调优、Buffer 预分配、V8 hidden classes 一致性)均为微优化,收益 < 1%
152
+
153
+ #### 代码质量与性能优化(第七轮 2026-03-22)
154
+ - **admin-api.ts `startService` fire-and-forget 竞态条件修复(正确性 bug)**: `serviceManager.start()` 原来是 fire-and-forget(不 await),如果启动命令失败但端口短暂可用,TCP 就绪循环会将状态错误地标记为 online。改为先 `await start()` 完成后再做 TCP 就绪检查
155
+ - **WebSocket handler 无条件 JSON.stringify 日志修复**: hostname 路由的 WebSocket `open` 回调中有一行 `JSON.stringify(backendHeaders, null, 2)` 日志没有 `enableWebSocketLog` 守卫,每次 WebSocket 连接都执行。改为仅在 `enableWebSocketLog` 开启时记录
156
+ - **CRLF 替换快速路径**: 热路径 `handleRequest` 和 `handlePortBindingRequest` 的 headers 收集中,先用 `value.includes('\r') || value.includes('\n')` 快速检查是否需要正则替换。正常请求(99.99%+)直接跳过 `replace()` 调用,节省 ~400-1800ns/req
157
+ - **fullUrl 拼接方式统一**: `handlePortBindingRequest` 中的模板字符串 `${url}?${queryString}` 改为字符串拼接 `url + '?' + queryString`,与 `handleRequest` 保持一致
158
+ - **移除 node-fetch 依赖**: `health-checker.ts` 中 `import fetch from 'node-fetch'` 改为使用 Node.js 22 内置的全局 `fetch` API。`pnpm remove node-fetch` 移除生产依赖,减小安装体积
159
+ - **212 个扩展测试全部通过**,基准测试 5,347 req/s(wrk -t4 -c50 -d10s),冷启动 201ms
160
+
161
+ #### 新增测试套件(第八轮 2026-03-22)
162
+ - **test-crlf-fastpath.ts**: 11 个 CRLF 安全性验证测试(新增)
163
+ - 正常原始 TCP 请求(验证 chunked 响应解析正确性)
164
+ - CRLF 快速路径正常请求不受影响
165
+ - URL 路径特殊字符安全
166
+ - uWS 层安全:裸 \n 被 uWS 拒绝 (400)
167
+ - uWS 层安全:裸 \r 被 uWS 拒绝或忽略
168
+ - uWS 层安全:\r\n+非法行被 uWS 拒绝 (400)
169
+ - uWS 层安全:\r\n+合法头被 uWS 解析为独立头(标准 HTTP 行为)
170
+ - uWS 层安全:\r\n+多个注入头解析
171
+ - CRLF 不产生额外响应头(响应头注入防护)
172
+ - 响应头注入防护
173
+ - 20 个并发 CRLF 请求不崩溃
174
+ - **test-gzip-passthrough.ts**: 5 个 Gzip 压缩响应透传测试(新增)
175
+ - gzip Content-Encoding 头透传(hostname 路由)
176
+ - gzip 响应体可解压验证
177
+ - 无 Accept-Encoding 时 gzip 透传
178
+ - 多 Accept-Encoding 时 gzip 透传
179
+ - 端口路由 gzip 响应透传
180
+ - **test-startservice-race.ts**: 6 个 startService 竞态条件修复验证测试(新增)
181
+ - startService 正常启动
182
+ - startService 后代理功能正常
183
+ - starting 状态重复调用返回 400
184
+ - online 状态调用返回 400
185
+ - startCount 正确递增
186
+ - 启动超时机制验证
187
+ - **test-port-ws-proxy.ts**: 10 个端口绑定 WebSocket 代理测试(新增)
188
+ - 端口路由 WS 基本连接与消息收发
189
+ - 端口路由 WS 二进制消息
190
+ - 端口路由 WS 较大消息 (10KB)
191
+ - 端口路由 WS 并发连接 (10个)
192
+ - 端口路由 WS 快速连接/断开循环 (20次)
193
+ - 端口路由 WS + HTTP 混合并发
194
+ - 端口路由 WS 按需启动
195
+ - 端口路由 WS 消息队列
196
+ - 端口路由 WS 长连接稳定性 (5s)
197
+ - 端口路由 WS 后端崩溃后连接清理
198
+
199
+ #### CRLF 安全架构分析结论
200
+ - **双层安全模型**: uWS HTTP 解析器(第一层)+ 网关 CRLF 清理(第二层)
201
+ - **uWS 解析器**: 裸 \n / \r 违反 HTTP 规范,uWS 直接返回 400 Bad Request
202
+ - **\r\n 行为**: uWS 将 \r\n 解析为 HTTP 头分隔符(标准行为),\r\n+合法头成为独立头,\r\n+非法行导致 400
203
+ - **网关 CRLF 清理**: 对 `req.forEach` 迭代的每个 header value 做防御性 `[\r\n]` 替换,保护通过程序化路径(如中间件)传入的脏数据
204
+ - **快速路径优化**: `value.includes('\r') || value.includes('\n')` 先检查,正常请求(99.99%+)跳过正则替换
205
+
206
+ #### 代码质量与性能优化(第六轮 2026-03-22)
207
+ - **admin-api.ts 删除重复的 `checkTcpPort` 函数**: 与 gateway.ts 中的实现功能完全相同,且每次调用都 `new URL()` 解析。改为在 `startService` 循环外预解析 URL,内联 TCP 检查逻辑
208
+ - **health-checker.ts 消除循环内 `new URL()` 冗余解析**: `wait` 方法在循环外预解析 `service.base` 为 `targetHost` 和 `targetPort`,传入 `checkTcp` 方法。`checkTcp` 签名改为直接接收 host/port 参数
209
+ - **admin-api.ts `method.toLowerCase()` 全部移除**: uWS `getMethod()` 返回小写方法名,5 处 `method.toLowerCase()` 是冗余操作。直接比较 `method === 'get'` / `method === 'post'`
210
+ - **168 个扩展测试全部通过**,基准测试 4,680 req/s(正常波动范围)
211
+
212
+ #### 代码质量与性能优化(第五轮 2026-03-22)
213
+ - **`Buffer.alloc` → `Buffer.allocUnsafe`**: `collectRequestBody` 和 `handleDirectProxy` 的 `onData` 回调中,`Buffer.alloc` 会先 memset 清零再被 `copy()` 覆盖。改用 `allocUnsafe` 跳过清零,减少每次回调的 CPU 开销。安全性分析:`Buffer.from(ab).copy(chunk)` 立即覆盖所有字节,不存在数据泄露风险
214
+ - **WebSocket headers 构建优化**: 两处 WebSocket `open` 回调中的 `Object.entries(clientHeaders)` + `key.toLowerCase()` 改为 `for...in` + 直接 `has(key)`。uWS `req.forEach` 的 key 已是小写,`WS_SKIP_HEADERS` 的 key 也是小写
215
+ - **复用 `startTime` 替代第二次 `Date.now()`**: `handleRequest` 和 `handlePortBindingRequest` 中 `service._state!.lastAccessTime` 直接使用 `startTime`,省掉一次系统调用(idle checker 精度 3 秒,差异可忽略)
216
+ - **代理请求超时返回 504 而非 502(功能性修复)**: `proxyReq.on('timeout')` 设置 `state.timedOut` 标志,`error` handler 据此区分返回 504 Gateway Timeout(超时)和 502 Bad Gateway(连接错误)。`handleDirectProxy` 和 `forwardProxyRequest` 两处修复
217
+ - **专用 HTTP Agent 评估**: 创建 `PROXY_AGENT`(maxSockets:256, maxFreeSockets:32)后基准测试显示 QPS 从 4,936 降到 4,214。原因:DynaPM 后端全在 localhost,TCP 握手 ~50us 极快,`maxSockets:Infinity` 不是问题;而 `maxFreeSockets:32`(默认 256)导致空闲连接频繁回收重建。已回退使用 `globalAgent`
218
+ - **TCP_NODELAY 确认**: Node.js v18+ 的 `http.ClientRequest` 默认已启用 TCP_NODELAY,无需额外设置
219
+ - **168 个扩展测试全部通过**,基准测试 4,954 req/s(3 服务×50 并发),P50 延迟 ~31ms
220
+
221
+ #### 代码质量与性能优化(第四轮 2026-03-22)
222
+
223
+ #### 代码质量与性能优化(第三轮 2026-03-22)
224
+ - **checkTcpPort 消除每次调用的 `new URL()` 开销**: 改为直接接收 `host` 和 `port` 参数,利用已缓存的 `RouteMapping.targetUrl`/`targetPort`;WebSocket 启动等待中也提前创建 `targetUrl` 避免重复解析
225
+ - **Admin API `findServiceMapping` O(n) → O(1)**: 构建懒初始化的 `serviceName → RouteMapping` 索引 Map,替代每次请求的线性遍历
226
+ - **Admin API `getServicesList` 消除重复遍历**: 使用预构建的服务名称索引 Map,替代每次请求时遍历所有路由表构建去重列表
227
+ - **178 个测试全部通过**(含新增的 8 个网关韧性测试)
228
+
229
+ #### 性能优化(第二轮 2026-03-21)
230
+ - **消除响应头过滤冗余 toLowerCase**: `proxyRes.headers` 的 key 已经是小写的,4 处 `.toLowerCase()` 调用是冗余的,移除后代码更正确
231
+ - **微基准验证**: CRLF 替换 includes 优化 13.5x(正常值)、一次遍历合并节省 22.6%——但综合影响 < 1% 的总延迟
232
+ - **确认 node:http 22 默认 globalAgent 已最优**: `keepAlive: true, maxSockets: Infinity`
233
+ - **架构瓶颈确认**: 所有 JS 层面微优化合计节省 ~300ns/req,在 34ms 延迟中占比 < 1%
234
+ - **最终结论**: 网关已接近 node:http 出站连接的理论极限,瓶颈在 HTTP 协议双重解析(客户端→uWS + node:http→后端)
235
+ - 基准测试:4,936 req/s(3 服务×50 并发),P50 延迟 ~31ms,170 个测试全部通过
236
+
237
+ #### 性能评估结论
238
+ - 网关纯代理开销 P50=0.006ms(6μs),在测量误差范围内,远低于 node:http 协议解析开销
239
+ - 1000 请求延迟剖析:TTFB P50=0.336ms,Total P50=0.360ms,Body overhead 仅 0.024ms
240
+ - 微基准测试:所有热路径操作均在亚微秒级别(Map.get 27ns、Set.has 28ns、CRLF replace 73ns、Buffer.alloc+copy 787ns)
241
+ - Buffer.alloc+copy 是最昂贵操作(787ns/op),但这是 uWS ArrayBuffer 借用语义的必要成本,无法优化
242
+ - 基准测试:冷启动 255ms、单请求延迟 9.9ms、3 服务×50 并发吞吐量 5,260 req/s
243
+ - **无数量级优化空间**: 瓶颈在 node:http 的 HTTP 协议双重解析(客户端→网关 + 网关→后端),不是网关代码
244
+ - node:http keep-alive 出站 0.097ms/req,新建连接 0.252ms/req,网关已利用 keep-alive
245
+ - **net.Socket 替代方案不可行**: 测试显示 net.Socket 0.508ms/req(无 keep-alive),反而更慢;uWS 未暴露 `us_socket_context_connect`
246
+ - undici 与 uWS 流式模型不兼容,不可用作替代方案
247
+ - Pilot 实际运行测试:16/16 全部通过(使用 dynapm.config.ts 生产配置)
248
+ - WebSocket 并发测试:10/10 全部通过(20 并发连接、混合 WS+HTTP、按需启动、闲置保护)
249
+
250
+ #### Serverless Host 演示
251
+ - test/services/serverless-host/: 独立目录结构
252
+ - index.ts: 后端服务(Worker 线程隔离执行 TS 函数)
253
+ - public/: 前端静态文件(CodeMirror 6 IDE 界面)
254
+ - 前端升级到 IDE 级别体验:
255
+ - CodeMirror 6 编辑器(语法高亮、自动缩进、行号)
256
+ - 可拖拽调整大小的侧边栏和输出面板
257
+ - 自定义请求体编辑面板(POST/PUT/PATCH)
258
+ - HTTP 方法选择、请求路径输入、模板下拉菜单
259
+ - JSON 语法高亮输出、快捷键面板(Ctrl+Enter 运行、Ctrl+S 保存)
260
+ - 脏状态标记、Toast 通知、函数删除确认
261
+ - 后端完善:
262
+ - 静态文件服务(pipe 流式传输、Cache-Control)
263
+ - GET /_fn/:name 读取函数源码端点
264
+ - 请求体大小限制(64KB)、请求日志
265
+ - 支持子路径执行(/:fnName/sub/path)
266
+
267
+ #### echo-server 新增端点
268
+ - `/cookie` — 返回 Set-Cookie 响应头
269
+ - `/custom-response` — 返回自定义响应头(X-Custom-Response、X-Rate-Limit、Cache-Control)和二进制响应体
270
+ - `/no-content` — 返回 204 No Content
271
+ - `/gzip` — 返回 gzip 压缩的 JSON 响应(Content-Encoding: gzip)
@@ -21,7 +21,15 @@ export declare class AdminApiHandler {
21
21
  private hostnameRoutes;
22
22
  private portRoutes;
23
23
  private serviceManager;
24
+ /** 按服务名称索引的服务配置(懒初始化,因为构造时路由表可能尚未填充) */
25
+ private _serviceMap;
26
+ /** 按服务名称索引的路由映射(懒初始化) */
27
+ private _routeMap;
24
28
  constructor(config: DynaPMConfig, logger: Logger, hostnameRoutes: Map<string, RouteMapping>, portRoutes: Map<number, RouteMapping>, serviceManager: ServiceManager);
29
+ /** 获取(或首次构建)服务名称索引 */
30
+ private getServiceMap;
31
+ /** 获取(或首次构建)路由映射索引 */
32
+ private getRouteMap;
25
33
  /**
26
34
  * 检查客户端 IP 是否在允许列表中
27
35
  */
@@ -34,6 +42,10 @@ export declare class AdminApiHandler {
34
42
  * 获取服务运行时长
35
43
  */
36
44
  private getServiceUptime;
45
+ /**
46
+ * 在所有路由表中查找服务
47
+ */
48
+ private findServiceMapping;
37
49
  /**
38
50
  * 处理管理 API 请求
39
51
  */