Iris 的 OPTIONS 预检请求被忽略是因为框架不自动拦截,必须显式注册 app.Options("*", handler) 或在 UseGlobal 中手动处理 ctx.Method() == "OPTIONS" 并返回 204 No Content,否则预检请求根本无法进入中间件逻辑。

为什么 Iris 的 OPTIONS 预检请求总被忽略?
Iris 默认不拦截 OPTIONS 请求,路由层直接跳过,导致浏览器预检失败、控制台报 Response to preflight request doesn't pass access control check,而服务端日志里根本看不到这条请求——它压根没进你的 handler。
这不是配置漏了,是框架设计使然:Iris 不像 Gin 或 Echo 那样自动响应预检。只要前端带了 Authorization、X-Requested-With 或任何非简单头,浏览器就发 OPTIONS,你必须显式处理。
- 只在业务 handler 里加
Access-Control-Allow-Origin没用,预检阶段已中断 -
app.UseGlobal()必须在所有app.Get()/app.Post()之前调用,否则中间件不生效 - 若用子路由器(如
api := app.Party("/api")),UseGlobal仍有效,但局部Use()不会覆盖预检逻辑
怎么写一个能过预检的最小可用 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, X-Api-Key")
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)是必须的,不能只写ctx.Next(),否则返回 200 + 空 body,部分浏览器会拒绝
生产环境怎么安全放开多个域名?
把硬编码的域名判断换成白名单切片遍历,避免字符串拼接或正则引入漏洞:
allowedOrigins := []string{
"https://app.example.com",
"https://admin.example.com",
"https://staging.example.com",
}
origin := ctx.GetHeader("Origin")
allowed := false
for _, o := range allowedOrigins {
if o == origin {
allowed = true
break
}
}
if !allowed {
ctx.Next()
return
}
// 后续设置 header & 处理 OPTIONS...
更关键的是:不要用 allowed_origins_patterns 类似机制(Iris 没内置),自己实现时别用 strings.Contains 或模糊匹配,防止 https://evil.com.example.com 绕过。
如果需支持子域名通配(如 *.example.com),必须手动解析 origin 主机名并做 strings.HasSuffix 判断,且确保不匹配 attacker-example.com 这类构造域名。
为什么加了中间件还是 404 或 500?
常见真因不是 CORS 配置错,而是中间件注册时机或路径冲突:
- 把
app.UseGlobal(...)写在app.Get("/api/user", ...)之后 → 中间件不生效 - 路由路径带前缀(如
app.Party("/v1")),但中间件里没考虑路径层级,ctx.Path()取值异常 - 中间件里调用
ctx.Next()后,后续 handler panic 了,但错误被 Iris 默认 recovery 捕获,表面看像 CORS 问题,实际是业务崩溃 - 用了第三方中间件(如 JWT 验证),它在 CORS 前执行且对
OPTIONS也做鉴权 → 直接 401,预检卡死
调试建议:先注释掉所有其他中间件,只留 CORS,确认预检能返回 204;再逐个加回,定位冲突点。CORS 中间件永远该是最外层之一,紧挨着 app.UseGlobal 调用位置。


















