iris 中需显式注册 options 路由并手动实现 cors 中间件,确保正确设置 access-control-allow-* 系列响应头、处理预检请求、校验 origin 白名单,且生产环境禁用通配符。

直接在 Iris 中注册全局 CORS 中间件
Iris 没有内置的 CORSMiddleware 类(不像 FastAPI 或 Express),必须手动编写或复用社区常用模式。最稳妥的做法是定义一个函数型中间件,在每个请求响应前注入标准 CORS 头。注意:不能只加 Access-Control-Allow-Origin,否则带认证头或自定义 header 的请求会失败。
常见错误现象是前端报错 Response to preflight request doesn't pass access control check,根本原因往往是没处理 OPTIONS 预检请求,或响应头缺失 Access-Control-Allow-Methods/Access-Control-Allow-Headers。
- 必须显式拦截并响应
OPTIONS方法,返回204 No Content,不能只靠ctx.Next() -
Access-Control-Allow-Origin设为"*"时,Access-Control-Allow-Credentials必须为false;若需传 cookie,就得指定具体 origin(如"http://localhost:3000") - 所有允许的 method 和 header 必须与前端实际发出的请求严格一致,比如前端发了
X-Auth-Token,就必须出现在Access-Control-Allow-Headers里
为什么 Iris 的 OPTIONS 路由必须显式注册?
Iris 不像 Laravel 或 FastAPI 那样自动捕获预检请求。如果你只在中间件里判断 ctx.Method() == "OPTIONS" 并返回,但没在路由表中注册对应路径的 OPTIONS handler,Iris 就不会触发该中间件——因为路由未匹配,中间件根本不会执行。
所以必须用 app.Options("*", ...) 或针对具体路径(如 /api/*)注册通配 OPTIONS 路由,确保预检请求能进到中间件逻辑里。
-
app.Use(Cors)只影响已注册的路由,对未声明的OPTIONS请求无效 - 推荐写法:
common := app.Party("/")后立刻调用common.Options("*", func(ctx iris.Context) { ctx.StatusCode(204) }) - 若 API 分组在
/api下,也应在api.Options("*", ...)单独注册,避免漏掉深层路径
生产环境必须避开 Access-Control-Allow-Origin: "*"
只要启用了 supports_credentials(比如前端设置了 credentials: 'include'),服务端就不能用通配符 "*" 作为 Access-Control-Allow-Origin 值,否则浏览器直接拒绝响应。Iris 中没有自动 origin 白名单校验,得自己写逻辑。
典型做法是在中间件里解析 ctx.GetHeader("Origin"),再比对预设白名单数组,匹配成功才写入该 origin,否则跳过或返回 403。
- 示例白名单检查:
allowedOrigins := []string{"https://myapp.com", "http://localhost:3000"} - 不要用字符串包含判断(如
strings.Contains(origin, "myapp.com")),容易被绕过;要用完整相等或正则精确匹配 - 如果前端 origin 是
null(常见于 file:// 协议或 iframe sandbox),多数情况下应拒绝,不写任何 CORS 头
性能与调试:别忽略 max-age 和浏览器 DevTools
Access-Control-Max-Age 控制预检结果缓存时长,设为 3600(1 小时)可显著减少重复 OPTIONS 请求。但 Iris 中间件不会自动加这个头,得手动写:ctx.Header("Access-Control-Max-Age", "3600")。
最容易被忽略的是验证环节:光看代码写了头,不等于浏览器收到了。每次改完配置,必须打开 Chrome DevTools → Network → 点开任意一个跨域请求 → 查看 Response Headers 里是否真实存在全部预期头,且值正确。
- 特别注意
Access-Control-Allow-Credentials的布尔值是字符串"true",不是 Go 的true字面量 - 如果后端用了反向代理(如 Nginx),它可能覆盖或删除响应头,此时要在代理层也透传 CORS 头
- 本地开发时,前端和后端端口不同(如
:3000vs:8080)是最常见触发跨域的场景,也是最该优先验证的用例











