Go标准库net/http完全不处理CORS,必须显式配置;带凭据请求禁用通配符Origin,需白名单校验并精确回写;OPTIONS预检须显式处理且头设置须在WriteHeader前。

Go 语言标准库 net/http 完全不处理 CORS,所有跨域逻辑必须由你显式控制——不是“配错”,而是“没配就根本不会发头”。
为什么手写 w.Header().Set("Access-Control-Allow-Origin", "*") 在生产环境会失效
这个写法在开发阶段看似能跑通,但一旦前端携带 Cookie 或 Authorization header,浏览器就会拒绝响应。因为 Access-Control-Allow-Credentials: true 和 Access-Control-Allow-Origin: "*" 是互斥的。
- 带凭据(如登录态)的请求,
AllowedOrigin必须是具体域名,不能用"*" - 如果前端发的是
https://localhost:3000,后端就必须精确匹配该字符串,大小写、协议、端口缺一不可 - 开发时常见坑:只允许
http://localhost:3000,但前端实际走的是https://localhost:3000(比如用了 HTTPS 代理),导致 origin 不匹配
gorilla/handlers.CORS 的 AllowedOrigins 参数怎么写才安全
别直接传 []string{"*"},也别硬编码一堆域名拼成 slice。真实项目里更常用的是动态白名单校验。
- 用函数式选项:
handlers.AllowedOriginsFunc(func(origin string) bool { return strings.HasSuffix(origin, ".example.com") || origin == "http://localhost:3000" }) - 若需支持多个开发环境,建议把允许的 origin 列表存在配置文件或环境变量中,启动时解析为
[]string - 注意:空字符串
""或nilorigin 会被某些浏览器当作file://协议处理,应显式过滤
预检请求(OPTIONS)被 404 或 500 怎么快速定位
浏览器发出 OPTIONS 请求后卡住或报错,说明你的 handler 没正确响应它——不是业务逻辑出错,而是连预检都没过。
立即学习“go语言免费学习笔记(深入)”;
- 检查是否在中间件或路由层提前返回了,比如
if r.Method == "OPTIONS" { w.WriteHeader(204); return }被写在了业务逻辑之后 - 用
curl -X OPTIONS -H "Origin: http://localhost:3000" -I http://localhost:8080/api/user直接测试,看响应头里有没有Access-Control-Allow-Origin - 如果用了
gorilla/mux,确保 OPTIONS 路由没被其他中间件拦截(比如 JWT 验证中间件未放行 OPTIONS)
rs/cors 和 gorilla/handlers 选哪个更稳
两者都可靠,但行为细节不同,容易踩坑的是 rs/cors 的默认 AllowedMethods 不含 PUT 或 DELETE,而 gorilla/handlers 默认也不包含,但文档更直白。
-
rs/cors:默认只放行GET、POST、HEAD;要支持DELETE,必须显式写AllowedMethods: []string{http.MethodGet, http.MethodPost, http.MethodDelete} -
gorilla/handlers:AllowedMethods若不指定,会 fallback 到["GET", "POST", "PUT", "DELETE", "OPTIONS"],但仅当没设AllowedOrigins时才生效,有歧义 - 性能上差异不大,但如果 origin 列表超 20 个,建议用
AllowedOriginsFunc配 map 查表,避免线性匹配
最常被忽略的一点:CORS 头必须出现在所有响应路径上——包括 401、404、500 错误响应。否则前端在错误场景下依然拿不到 Access-Control-Allow-Origin,导致 fetch 报 “opaque” 错误而非真实状态码。


















