axios put跨域失败主因是gin未正确处理options预检:需显式响应204并设置access-control-allow-methods含put、access-control-allow-headers覆盖实际请求头(如token、content-type),且withcredentials为true时access-control-allow-origin不能为*。

直接结论:Axios 发送 PUT 请求跨域失败,90% 是因为 Gin 没正确处理 OPTIONS 预检请求,或 Access-Control-Allow-Methods 里漏了 PUT,或 Access-Control-Allow-Headers 没覆盖你实际发的自定义头(比如 token、X-Request-ID)。
为什么 PUT 请求会触发 OPTIONS 预检?
浏览器对非“简单请求”自动发起 OPTIONS 预检。PUT 属于非简单方法,且 Axios 默认带 Content-Type: application/json(也不在简单头列表里),所以必走预检。Gin 若没拦截并响应 OPTIONS,请求就卡在预检阶段,控制台报错:Response to preflight request doesn't pass access control check。
常见错误现象:
- Chrome Network 面板看到第一个请求是
OPTIONS,状态码 404 或 500,后续 PUT 不发出 - 控制台明确提示缺失
Access-Control-Allow-Origin或Access-Control-Allow-Methods - 用 curl 直接调用 PUT 接口成功,但浏览器里失败 → 纯 CORS 配置问题
Gin 中间件必须显式处理 OPTIONS 方法
不能只设 Header 就完事。Gin 的中间件必须在 OPTIONS 请求到达业务逻辑前终止它,并返回 204(StatusNoContent)。
正确做法:
- 检查
c.Request.Method == "OPTIONS",满足则调用c.AbortWithStatus(http.StatusNoContent) - 这个判断必须放在设置所有
Access-Control-*Header 之后、c.Next()之前 - 如果用了
gin-contrib/cors,它已内置该逻辑;但手写中间件时极易漏掉这一步
示例关键片段:
前端设计与 UI/UX 全方位优化专家。覆盖视觉层次、排版系统、色彩理论、响应式布局、交互体验、动画动效、无障碍访问、性能优化八大维度,帮助开发者将普通页面升级为高品质产品级界面。前端设计与 UI/UX 全方位优化专家。覆盖视觉层次、排版系统、色彩理论、响应式布局、交互体验、动画动效、无障碍访问、性能优化八大维度,帮助开发者将普通页面升级为高品质产品级界面。
func Cors() gin.HandlerFunc {
return func(c *gin.Context) {
origin := c.Request.Header.Get("Origin")
if origin != "" {
c.Header("Access-Control-Allow-Origin", "https://your-frontend.com")
c.Header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
c.Header("Access-Control-Allow-Headers", "Origin, Content-Type, Authorization, X-Requested-With, token")
c.Header("Access-Control-Allow-Credentials", "true")
c.Header("Access-Control-Expose-Headers", "Content-Length")
}
if c.Request.Method == "OPTIONS" {
c.AbortWithStatus(http.StatusNoContent) // ← 这行不能少
return
}
c.Next()
}
}
Access-Control-Allow-Headers 必须精确匹配 Axios 实际发送的头
Axios 默认不发额外头,但一旦你手动加了(比如 config.headers.token = localStorage.token),就必须出现在 Access-Control-Allow-Headers 列表里,且大小写不敏感但拼写必须一致。
容易踩的坑:
- 写了
"Token"但前端发的是"token"→ 不匹配(实际可忽略大小写,但建议统一小写) - 漏掉
Content-Type:Axios PUT 默认用application/json,而Content-Type是预检必验头,必须显式声明 - 用
*替代列表 →Access-Control-Allow-Headers: "*"在带credentials时无效,会被浏览器拒绝 - 后端读取 header 名用
c.Request.Header.Get("Token"),但 CORS 响应头里写的是"token"→ 没问题,但别混淆“接收”和“声明”
前端 Axios 配置需与后端 CORS 设置对齐
前后端必须协同:后端允许什么,前端才敢发什么。
关键点:
-
withCredentials: true时,Access-Control-Allow-Origin不能为*,必须是具体域名(如https://your-frontend.com) - 若后端设了
Access-Control-Allow-Credentials: "true",前端必须开withCredentials,否则浏览器不带 cookie/token - PUT 请求体是 JSON?确保后端用
c.ShouldBindJSON(&data)而不是c.PostForm,否则解析失败看似跨域问题
最小可用 Axios 配置示例:
axios.put('http://localhost:8080/api/item/123', { name: 'test' }, {
withCredentials: true,
headers: { 'token': 'abc123' }
})
真正麻烦的从来不是加几行 Header,而是 OPTIONS 请求被静默吞掉、或 Allow-Headers 和实际请求头对不上——这两处一错,PUT 就永远卡在预检。调试时先看 Network 里 OPTIONS 响应头是否完整,再比对请求头字段,比瞎猜快十倍。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










