OPTIONS预检失败主因是中间件未执行或未正确响应,需确保CORS中间件在所有路由前注册、不被其他中间件中断,且AllowCredentials为true时AllowOrigins必须指定具体域名而非*。

为什么 OPTIONS 请求总失败?
不是后端没写 OPTIONS 路由,而是浏览器自动发的预检请求被中间件拦截或跳过。Gin 默认不处理 OPTIONS 方法,除非显式配置 CORS 中间件响应它。
常见错误现象:Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present,说明中间件根本没执行,或者执行了但没对 OPTIONS 返回头。
- 确保 CORS 中间件在所有路由之前注册:
router.Use(cors.New(...)),不能只挂到某组路由下 - 检查中间件是否被其他中间件(如 JWT 鉴权)提前中断:如果鉴权中间件对
OPTIONS也做校验且未放行,就会 401 或直接 panic -
AllowCredentials: true时,AllowOrigins不能为"*",否则浏览器拒绝——必须指定具体 origin,例如[]string{"http://localhost:3000"}
前端带 Cookie 时后端怎么配才生效?
前后端必须“双向约定”:前端发请求要带 credentials: 'include',后端响应头必须同时满足三个条件,缺一不可。
- 后端
AllowCredentials设为true - 后端
AllowOrigins不能用"*",得写死域名,比如[]string{"https://admin.example.com"} - 后端响应头必须包含
Access-Control-Allow-Credentials: true,且该头不能被其他中间件覆盖或遗漏
漏掉任意一条,浏览器都会静默丢弃响应体,控制台只报 CORS 错误,不提示具体哪条没满足。
生产环境为何不能用 allowOrigins: "*"?
因为 Access-Control-Allow-Origin: "*" 和 Access-Control-Allow-Credentials: true 是互斥的。一旦你开了凭证支持(比如登录态依赖 Cookie),就必须显式列出可信任的 origin。
- 开发期用
"*"图省事,上线后必须改;否则带credentials的请求全失败 - 多个前端域名需全部列进
AllowOrigins切片,顺序无关,但不能遗漏 - 如果 origin 动态多变(如不同租户子域名),用
AllowOriginFunc替代静态列表,函数返回true才放行
为什么加了 CORS 还是 404?
这不是跨域问题,是路由没匹配到。CORS 中间件只管加响应头,不负责路由转发。常见于:
- 前端请求路径写错(比如少了个
/api前缀),后端根本没有对应 handler - 中间件注册顺序错误:CORS 放在了
router.NoRoute之后,导致 404 响应压根不经过 CORS - Gin 版本差异:老版本("/" 的 OPTIONS 处理有 bug,升级到最新版可规避
排查时先关掉 CORS,用 curl 直接请求后端接口看是否返回 200;再开 CORS,对比响应头是否含 Access-Control-Allow-Origin —— 分清是路由问题还是跨域问题。


















