Files
go-omni/reports/corsAcceptance.md

77 lines
6.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# v0.24 CORS 验收(2026-09-26)
新增通用、可选的跨域策略。没有修改接入项目,没有连接业务数据库或对线上服务器进行压测。
## 回归
- `GO_OMNI_SCAFFOLD_INTEGRATION=1 go test -race ./...`:49 个有测试的包通过,包含实际生成消费者和既有生命周期、错误目录、配置、上传下载等回归。
- 最后补充 IPv4-mapped IPv6 来源序列化后,cors/config/app 的 race 复测通过。
- Go 1.22.12 的 cors/config/app 测试通过;`go vet ./...`、`go build ./...` 通过。
- 最后补充来源序列化后,同三个包在 Go 1.22.12 上复测通过。
- managedService 重生成检查、race、根目录 build 通过;userService race 通过。没有提供外部数据库配置的测试按原规则跳过。
- 实际生成的 CORS 消费者只修改配置,不修改 main、svc、handler;构建/race、重复生成、dry-run、check、业务文件字节保留通过。
- `FuzzCORSHeaders` 运行 30 秒、4 worker,执行 2,877,406 次,通过。输入覆盖来源、方法和预检请求头,不等于穷尽所有协议组合。
- `examples/cors` 使用本地临时监听端口验证 204、401、200、404,通过。
| 范围 | 已验证场景 |
| --- | --- |
| 默认与配置 | 默认关闭保持原 Handler;JSON/YAML/XML 一致;显式环境引用;配置错误定位 server.cors 具体字段及文件/环境名/可用位置,不输出值 |
| 来源 | 精确协议/域名/端口、默认端口规范化、IPv6、恶意后缀、null/路径/CRLF 拒绝;通配来源禁止凭据;重复 Origin 拒绝 |
| 预检 | 204 空响应,拒绝为 403;不进入业务鉴权;方法/头校验、大小与数量限制;普通 OPTIONS 仍进入项目 Handler |
| 实际响应 | 业务鉴权保留;自定义数字响应、401/500/panic、404/405 保留跨域头和原响应;不允许来源仅不授予浏览器读取权限 |
| 标准能力 | 原 Request/Context/Body/ResponseWriter 不替换,Flush 等能力保留;Vary 追加/去重,已有值和通配 Vary 保留 |
| transport | nethttp/native/HTTP2 使用真实本地 TLS;预检、原始上传、流式下载、暴露文件名、404 与关闭;HTTP2 确认协议协商 |
| 隔离 | 输入配置、Option、Config() 返回值的切片变更不改变已构建策略;32 个并发调用者各执行 100 次检查,race 通过 |
| 生成项目 | 未实现 Logic 的 501、404/405、健康检查、OpenAPI 和预检采用同一配置;非法凭据/通配组合在启动前报错 |
## 浏览器
通过 Codex In-app Browser,在两个不同的临时 localhost 页面分别执行 10 项真实 fetch 检查,共 20 项通过。记录见 [corsBrowser.json](corsBrowser.json)。
允许来源能读取正常响应、401、404、下载文件名,Authorization 触发的预检通过;不允许的请求头/方法被浏览器拦截。未列入白名单的页面无法读取私有 API;无凭据通配 API 可读取,带 `credentials: include` 的通配请求被拦截。凭据模式测试使用临时演示请求,未设置或使用真实登录 Cookie。
复现:在框架根目录 `go run ./scripts/corsBrowser`,打开终端输出的两个页面地址并点击 Run checks。脚本只监听 127.0.0.1,接收退出信号或五分钟后关闭。它用于浏览器协议验证,不是部署服务。本次临时监听已停止。
## 性能
Go 1.27.1、darwin/arm64、Apple M2 Max,无 race;每场景三轮、benchtime=300ms,表中取中位数。[原始结果](corsBenchmark.txt)。
| 场景 | 时间/次 | 分配/次 |
| --- | ---: | ---: |
| 关闭 CORS | 3.357 ns | 0 B / 0 allocs |
| 开启,无 Origin | 108.2 ns | 16 B / 1 alloc |
| 精确来源允许,含两个暴露头 | 231.5 ns | 48 B / 3 allocs |
| 来源不允许 | 130.4 ns | 16 B / 1 alloc |
| 允许预检 | 589.7 ns | 176 B / 7 allocs |
| 通配来源,无凭据 | 510.3 ns | 216 B / 5 allocs |
关闭时直接返回原 Handler,表中是基准循环与下游空 Handler 的耗时,不能理解为新增延迟。开启时使用预建请求、复用 Header map 的测试 Writer;不包含网络、TLS 或业务处理,不能换算成实际服务 QPS。精确白名单只查初始化时建立的表;通配模式还会验证传入来源是否合法,因此更慢。请求和响应体不进入本模块内存缓冲。
```sh
go test ./cors -run '^$' -bench BenchmarkCORS -benchmem -benchtime=300ms -count=3
go test ./cors -run '^$' -fuzz '^FuzzCORSHeaders$' -fuzztime=30s -parallel=4
GO_OMNI_SCAFFOLD_INTEGRATION=1 go test -race ./cmd/go-omni/apigen -run '^TestGeneratedCORSConsumer$'
```
## 边界
预检按应用策略判断,不探测每条路由。业务访问日志和指标不统计被 CORS 提前结束的预检,可在代理或 App 外层记录。网络解析/TLS/网络过载等进入 App 前的拒绝不由 CORS 改写。
默认关闭,同源反向代理可继续使用原部署方式。只支持 HTTP(S) 精确来源或单一无凭据通配来源,不提供子域通配/正则/null 来源。WebSocket Origin、Private Network Access 和对象存储自身的 CORS 属于其他接口,本轮不包含。
不批准来源不等于阻止服务端执行实际请求,项目的身份认证、权限和 CSRF 策略仍然必要。代理和应用只选择一处负责 CORS,下游不能覆盖许可头或 Vary。详细用法见 [cors 指南](../cors/README.md)。
## 远程版本验收
`v0.24.0-preview` 标签固定在 `800974cfff6228c2697373d9961d3c7c75611d08`。空 module 缓存安装远程 CLI,生成项目固定引用远程框架版本,无本地 replace;checksum 为 `h1:tHQSk+XawxJLWnN60so45GoA9An0m1xw5GFU8Ds1NoQ=`。
验收耗时 66.78 秒,70 项检查通过。9 组实际生成消费者执行 race/build;新增 CORS 消费者只改配置即可使用,重复生成/check 保留业务文件。下载模块的 cors/app 全包 race 通过,含三种 transport 的真实 TLS 检查;此前 config/httpc/copyx/logx、初始化/监听失败清理、后台关闭顺序、错误目录继承、上传下载、workspace 等回归继续通过。
版本、检查项及源码哈希见 [corsRemote.json](corsRemote.json)。复现命令:
```sh
python3 scripts/verifyManagedRelease.py --version v0.24.0-preview --report reports/corsRemote.json
```
发布标签不随此验收记录提交移动。