Files
go-omni/reports/corsAcceptance.md

5.2 KiB
Raw Blame History

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 ./... 通过。
  • 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。

允许来源能读取正常响应、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,表中取中位数。原始结果。

场景 时间/次 分配/次
关闭 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。精确白名单只查初始化时建立的表;通配模式还会验证传入来源是否合法,因此更慢。请求和响应体不进入本模块内存缓冲。

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 指南。