go http server 默认不支持cors,需手动添加响应头或使用gorilla/handlers等中间件;允许凭据时须指定具体域名并设置access-control-allow-credentials:true;预检请求需显式处理,开发时应同时允许localhost和127.0.0.1不同端口。

Go HTTP Server 默认不带 CORS 头,必须手动加
Go 标准库 net/http 完全不管跨域,浏览器看到没 Access-Control-Allow-Origin 就直接拦请求。不是“没生效”,是压根没发——连头都不加。别指望中间件自动补,也别查文档找“内置 CORS 支持”,它真没有。
常见错误现象:Failed to fetch 或控制台报 No 'Access-Control-Allow-Origin' header is present,但后端日志里请求其实已到达(说明不是网络或路由问题)。
- 最简方案:在 handler 里手写
w.Header().Set("Access-Control-Allow-Origin", "*") - 但
*不支持带凭据(如 cookies、Authorization header),要带凭据就得写具体域名,且必须同步设Access-Control-Allow-Credentials: true - 预检请求(OPTIONS)必须显式处理,标准
http.ServeMux不会自动回 204,得自己写分支判断r.Method == "OPTIONS"
用 gorilla/handlers 是最省心的第三方选择
gorilla/handlers 是 Go 生态里事实标准的 CORS 中间件,比自己拼 header 稳定,也比抄网上的“三行 CORS”代码考虑更全(比如 Vary header、多 origin 匹配、expose headers)。
使用场景:API 服务需要支持前端不同环境(localhost:3000 / staging.example.com / prod.example.com);需要暴露自定义响应头如 X-Request-ID;要兼容老 IE(需 Access-Control-Allow-Headers: X-Requested-With)。
立即学习“go语言免费学习笔记(深入)”;
- 基础用法:
handlers.CORS(handlers.AllowedOrigins([]string{"http://localhost:3000"}))(myHandler) - 带凭据必须配对:
handlers.AllowedOrigins不能用*,且得加handlers.ExposedHeaders([]string{"X-Total-Count"})才能让前端读到分页总数这类字段 - 注意
handlers.CORS返回的是http.Handler,别误传给http.HandleFunc(后者要函数,不是 handler 实例)
gin-gonic/gin 的 CORS 中间件参数容易配错
如果你用 gin,gin-contrib/cors 提供了封装,但几个关键配置项语义和直觉相反,不看源码很容易翻车。
性能影响:每次请求都会做 origin 字符串匹配,如果 AllowedOrigins 列表太长(比如上百个域名),建议改用正则或前置 map 查表,避免线性遍历。
-
Config{AllowOrigins: []string{"*"}}—— 这个*允许任意 origin,但会禁用 credentials,和标准行为一致 -
AllowOriginsFunc比AllowOrigins更灵活,适合白名单动态加载(比如从 DB 或 Redis 读),但函数里别做阻塞操作 - 漏掉
AllowHeaders: []string{"Content-Type", "Authorization"}?那带 token 的请求会被预检拦住,错误信息是Request header field authorization is not allowed by Access-Control-Allow-Headers
开发时 localhost 端口不同也算跨域,别信“同源就不用配”
前端跑 http://localhost:3000,后端跑 http://localhost:8080,协议+域名相同但端口不同 → 严格跨域。浏览器不会放行,哪怕你本地测试觉得“应该没问题”。
容易被忽略的地方:Webpack DevServer 的 proxy 配置只是开发期转发,不解决真实跨域逻辑;而某些 IDE 内置服务器(如 VS Code Live Server)默认开的是 http://127.0.0.1:5500,和 localhost 在部分浏览器里也被视为不同 origin。
- 开发阶段最稳妥:后端允许
http://localhost:3000和http://127.0.0.1:3000两个 origin - 别在生产环境用
*,Nginx 层或 API 网关上做 origin 白名单更安全 - CORS 是浏览器机制,curl 或 Postman 测不出问题,必须用真实页面发起请求才触发










