Skip to content

feat: [EPIC-GW-04] 搭建网络访问面骨架 (HTTP/WS/SSE)#312

Merged
phantom5099 merged 4 commits into
1024XEngineer:mainfrom
pionxe:main
Apr 16, 2026
Merged

feat: [EPIC-GW-04] 搭建网络访问面骨架 (HTTP/WS/SSE)#312
phantom5099 merged 4 commits into
1024XEngineer:mainfrom
pionxe:main

Conversation

@pionxe

@pionxe pionxe commented Apr 15, 2026

Copy link
Copy Markdown
Collaborator

🎯 目标 (Motivation & Context)

本 PR 落地了网关重构计划的第四步 [EPIC-GW-04]。 为了让 NeoCode 能够作为底座服务于未来的 Web UI、富文本 TUI 等多模态客户端,我们在原有的 IPC 控制面之外,平行增加了一套 网络访问面 (Network Access Plane)

💡 MVP 设计原则说明:

  • 默认安全隔离:网络端点默认死锁绑定在 127.0.0.1:8080,利用操作系统 Loopback 机制进行物理隔离,本期暂不引入复杂的 Token 鉴权体系。
  • 协议绝对统一:无论外界是通过 Unix Socket、HTTP POST 还是 WebSocket 连入,底层逻辑全部归一化为标准的 JSON-RPC 2.0,所有入口共享一套鉴权、限流与业务路由。

Closes #304

✨ 主要变更 (Key Changes)

1. 三端点网络骨架 (internal/gateway/network_server.go)

  • POST /rpc:标准 HTTP 短连接入口,用于单次指令下发。
  • GET /ws:WebSocket 双向长连接入口,支持后续的流式打字机交互。
  • GET /sse:Server-Sent Events 单向流入口,针对 MVP 场景(gateway.ping)实现了触发即订阅及自动心跳保活。

2. 核心架构解耦与复用 (internal/gateway/rpc_dispatch.go)

  • 抽离出统一的 rpc_dispatch.go 分发器。
  • IPC Server 与 Network Server 不再各自为战,彻底消除重复的 MessageFrame 转换与 Error 映射代码。

3. 工程化与治理基线 (Governance)

  • CORS 支持:全局注入标准化跨域头并接管 OPTIONS 预检请求,为前端直连铺平道路。
  • 优雅退出 (Graceful Shutdown):通过并发安全的 sync.Mutex 维护长连接池,当进程收到终止信号时,主动切断所有休眠的 WS/SSE 阻塞 I/O,确保 neocode gateway 能够极速退出。
  • 修复了 404/405 边缘路由的兜底处理,确保任意错误入口均返回标准 JSON-RPC 格式。

4. 🧹 Chore: TUI Infra 测试修复

  • 顺手修复了 internal/tui/infraclipboardimage 模块在多平台 CI 下的 flaky 测试遗留问题。

✅ 验收标准 (Acceptance Criteria)

  • CLI 支持 --http-listen 参数,网关可同时启动 IPC 与 HTTP 服务而不互相阻塞。
  • curl POST /rpc 可成功调用 gateway.ping 并获得标准响应。
  • WS 与 SSE 管道测试连通,且进程退出时不会发生 Goroutine 挂死。
  • 尝试绑定 0.0.0.0 等非 Loopback 地址时,被安全策略明确拒绝。

🧪 测试与验证结果 (Verification)

  • 网络面核心逻辑(包含连接生命周期管理、CORS、长短连接收发)单元测试全量覆盖。

  • go test ./... 全仓 0 失败通过。

  • 本地冒烟测试指令 (供 Reviewer 验证):

      # 启动网关
      $ go run ./cmd/neocode gateway
    
      # 1. 验证 HTTP
      $ curl -X POST http://127.0.0.1:8080/rpc -H "Content-Type: application/json" -d '{"jsonrpc": "2.0", "method": "gateway.ping", "id": 1}'
    
      # 2. 验证 SSE 心跳
      $ curl -N http://127.0.0.1:8080/sse
    

@pionxe

pionxe commented Apr 15, 2026

Copy link
Copy Markdown
Collaborator Author

/review

fennoai[bot]

This comment was marked as outdated.

fennoai[bot]

This comment was marked as outdated.

fennoai[bot]

This comment was marked as outdated.

fennoai[bot]

This comment was marked as outdated.

fennoai[bot]

This comment was marked as outdated.

@codecov

codecov Bot commented Apr 15, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.99363% with 33 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
internal/gateway/network_server.go 93.45% 17 Missing and 9 partials ⚠️
internal/cli/gateway_commands.go 80.00% 5 Missing and 1 partial ⚠️
internal/tui/infra/image.go 83.33% 0 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

fennoai[bot]

This comment was marked as outdated.

1. 安全收敛:移除 CORS 全局放行,引入严格的 Origin 白名单(仅限 localhost/app 协议),并同步防御 WebSocket 跨站握手劫持 (CSRF)。
2. 稳定性修复:移除 WS 循环中死板的 ReadTimeout,防止纯接收型健康长连接被误杀。
3. 健壮性增强:为每个 WS 连接绑定独立的 context.CancelFunc,在连接异常或服务关停时精准中断下游 Runtime 任务,彻底杜绝协程泄漏。
4. 测试达标:补齐网络面边缘用例断言,模块覆盖率稳居 95% 以上。
@pionxe

pionxe commented Apr 15, 2026

Copy link
Copy Markdown
Collaborator Author

/review

@fennoai fennoai Bot mentioned this pull request Apr 15, 2026
fennoai[bot]

This comment was marked as outdated.

处理 Code Review 的最后边缘场景反馈,进一步提升网络访问面的一致性与系统健壮性:

1. 网络一致性修复:将 IPv6 环回地址 (http://[::1]) 及其带端口的形态正式纳入 CORS 与 WebSocket 的 Origin 校验白名单。修复了网关允许绑定 IPv6 却拦截其同源请求的自相矛盾问题。
2. 状态机逻辑修正:修复 TUI infra 层的本地剪贴板读取逻辑。当剪贴板无图片内容时,正确返回空状态 (nil, nil) 而非抛出“该平台不支持”的异常,避免上游 TUI 抛出错误告警。
3. 文档契约对齐:在 README.md 网络端点章节补充详尽的 Origin 安全白名单声明(限 localhost / 127.0.0.1 / [::1] / app://),消除未来第三方前端接入时的调试盲区。
4. 测试同步:同步更新网络面跨域测试与 infra 层断言用例,网关核心覆盖率稳居 95.3%。
@pionxe

pionxe commented Apr 16, 2026

Copy link
Copy Markdown
Collaborator Author

/review

@fennoai fennoai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found 3 issues worth addressing before merging: one startup regression risk, one loopback validation gap, and one docs/behavior mismatch around Origin enforcement.

cmd.Flags().StringVar(
&options.HTTPAddress,
"http-listen",
gateway.DefaultNetworkListenAddress,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--http-listen defaults to fixed 127.0.0.1:8080, and the command now treats network listener failure as fatal for the whole gateway startup. This is a behavioral regression vs prior IPC-only startup: if 8080 is occupied, gateway cannot start at all. Consider making network listener opt-in, defaulting to :0, or degrading gracefully when only the network plane fails.

Comment thread internal/gateway/network_server.go Outdated
if normalizedHost == "" {
return fmt.Errorf("invalid --http-listen %q: host must be loopback", address)
}
if strings.EqualFold(normalizedHost, "localhost") {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Loopback validation currently accepts localhost without resolving it. That weakens the "loopback-only" guarantee because hostname resolution can be environment-dependent. Recommend either requiring literal loopback IPs only, or resolving hostname and verifying every resolved address is loopback before accepting.

Comment thread README.md
`http://localhost`、`http://127.0.0.1`、`http://[::1]` 以及 `app://` 前缀来源连入;
非允许来源的跨域调用会被拦截并返回 `403`。

URL Scheme 派发骨架命令(EPIC-GW-02A):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Docs say only allowlisted origins are allowed, but implementation permits requests with empty Origin (including WS handshake with no origin). Please clarify this in README (e.g. "allowlist applies to requests that include Origin") or tighten server behavior to match current wording.

解决网络层边缘状态与可用性问题,保障本地核心服务的极高存活率:

1. 优雅降级 (Graceful Degradation):解耦网络面与核心 IPC 通道的生命周期。当 HTTP 监听失败(如 8080 端口冲突被占用)时,不再触发进程 Fatal,而是转为输出 Warning 告警,确保网关底层 IPC 继续为本地应用提供服务。
2. 严格的环回校验 (Loopback Resolution):消除了原先仅依赖字符串比对 localhost 的安全盲区。现引入真实的 DNS 解析,强制验证域名对应的所有 IP 均为 Loopback 地址,防御特定环境下的解析污染。
3. 契约文档对齐 (Docs):在 README 中明确注明 Origin 安全拦截机制的生效范围。澄清了非浏览器客户端(如 cURL、Postman、本地后端脚本)等不携带 Origin 头的请求会被正常放行,消除调用方的调试疑虑。
@phantom5099 phantom5099 merged commit bf7b316 into 1024XEngineer:main Apr 16, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[EPIC-GW-04] 网络访问面骨架(HTTP / WebSocket / SSE)

2 participants