iris框架默认不处理options预检请求,因其路由层不自动拦截该方法,需手动注册中间件统一返回204并设置access-control-allow-origin等头;否则预检失败且服务端无日志。

Iris 框架没有内置 CORS 中间件,必须手动注册自定义中间件或使用第三方封装,否则 Access-Control-Allow-Origin 等响应头不会自动添加。
为什么 Iris 默认不处理 OPTIONS 预检请求
Iris 不像 Gin 或 Echo 那样默认拦截并响应 OPTIONS 请求。当浏览器发起带认证头(如 Authorization)或自定义头的跨域请求时,会先发一个预检请求;如果服务端没返回正确响应头(比如 Access-Control-Allow-Methods),请求直接失败,且后端日志里可能看不到该请求——因为被 Iris 的路由匹配逻辑跳过了。
常见现象:Failed to fetch、控制台报 Response to preflight request doesn't pass access control check,但服务端无日志。
- 必须显式注册一个中间件,对
OPTIONS方法统一返回 204 并设置 CORS 头 - 不能只在 handler 里加 header,否则预检阶段就已中断
- 若用
app.UseGlobal,需确保它在所有路由注册前调用
最简可用的 CORS 中间件写法
以下代码可直接复制进 main.go,适配大多数开发场景(如前端跑在 http://localhost:3000):
app.UseGlobal(func(ctx iris.Context) {
origin := ctx.GetHeader("Origin")
if origin == "" {
ctx.Next()
return
}
// 允许的源,生产环境请替换为白名单切片 + 循环比对
if origin == "http://localhost:3000" || origin == "https://your-frontend.com" {
ctx.Header("Access-Control-Allow-Origin", origin)
ctx.Header("Access-Control-Allow-Credentials", "true")
ctx.Header("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With")
ctx.Header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
ctx.Header("Access-Control-Expose-Headers", "Authorization")
ctx.Header("Access-Control-Max-Age", "3600")
}
if ctx.Method() == "OPTIONS" {
ctx.StatusCode(iris.StatusNoContent)
return
}
ctx.Next()
})
注意点:
-
Access-Control-Allow-Origin不能和Access-Control-Allow-Credentials: true同时设为*,否则浏览器拒绝;必须指定具体域名 -
Access-Control-Allow-Headers要包含前端实际发送的自定义头,比如X-Api-Key就得加进去 -
ctx.StatusCode(iris.StatusNoContent)是必须的,仅写return会导致空响应体 + 200 状态码,部分浏览器仍报错
路径级细粒度控制(比如只放开 /api/**)
用 app.Use 替代 app.UseGlobal,并配合路由组:
api := app.Party("/api")
api.Use(func(ctx iris.Context) {
// 同上 CORS 头逻辑,但只作用于 /api 下所有路由
if ctx.Method() == "OPTIONS" {
ctx.Header("Access-Control-Allow-Origin", "http://localhost:3000")
ctx.Header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE")
ctx.StatusCode(iris.StatusNoContent)
return
}
ctx.Next()
})
这种写法的好处:
- 静态资源(如
/assets/)、健康检查接口(如/healthz)不受影响 - 不同 API 分组可配置不同
allowed_origins,例如管理后台和用户端分离部署 - 避免在非 API 路由中误加 CORS 头,减少响应体积
真正容易被忽略的是:CORS 头必须在预检响应中完整出现,且 Access-Control-Allow-Origin 值必须与请求头 Origin 完全一致(包括末尾斜杠)。哪怕多一个空格、少一个协议,浏览器都会判定失败。调试时务必用 curl -v -H "Origin: http://localhost:3000" -X OPTIONS http://localhost:8080/api/test 直接验证响应头。











