最稳妥方式是手动编写函数型中间件,显式设置CORS响应头并拦截处理OPTIONS预检请求;因Iris无内置CORS中间件,必须自行注入Access-Control-Allow-Origin等头,且需注册通配OPTIONS路由(如api.Options("*", handler))确保预检可达。

直接在 Iris 中启用跨域,最稳妥的方式是写一个中间件手动设置响应头,并显式处理 OPTIONS 预检请求——框架本身不提供开箱即用的 CORS 中间件,不像 Gin 有 gin.Cors() 那样封装好的函数。
为什么 Iris 没有内置 CORS 中间件
Iris 的设计哲学偏向显式控制:它把跨域响应头、预检逻辑、方法/头白名单等全部交由开发者自己组合。这避免了隐式行为带来的调试困难,但也意味着你不能只调用一个函数就完事。
常见错误现象包括:
- 前端发
POST带Authorization或自定义 header 时,浏览器先发OPTIONS请求,但服务端没响应或返回 404,导致整个请求被拦住 - 设置了
Access-Control-Allow-Origin: *,但又带了Credentials(如 cookie),浏览器直接拒绝(*和credentials: true互斥) - 没调用
ctx.Next(),导致后续 handler 不执行
手写 Cors 中间件的最小可行写法
以下是一个生产可用、覆盖主流场景的中间件片段(注意顺序和判断逻辑):
func Cors(ctx iris.Context) {
origin := ctx.GetHeader("Origin")
if origin == "" {
ctx.Next()
return
}
<pre class="brush:php;toolbar:false;">// 允许指定源(更安全),或用 *(仅限无 credentials 场景)
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, PATCH, OPTIONS")
ctx.Header("Access-Control-Expose-Headers", "Content-Length, X-Total-Count")
if ctx.Method() == "OPTIONS" {
ctx.StatusCode(204)
return
}
ctx.Next()}
关键点说明:
-
Access-Control-Allow-Origin不要硬写"*",尤其当你要支持 cookie 或 token 透传时,必须回传实际Origin值 -
Access-Control-Allow-Credentials: "true"必须配合 Origin 白名单,否则浏览器会忽略 -
OPTIONS请求必须终止在中间件里(不调ctx.Next()),且状态码设为204(不是 200) - 如果路由没注册
OPTIONS方法,Iris 默认不会自动响应预检,所以中间件里必须拦截并返回
如何挂载并确保 OPTIONS 路由生效
Iris 的路由匹配是精确的,app.Use(Cors) 只影响已注册的路由。如果你的 API 是 /api/users,但没显式声明 OPTIONS /api/users,浏览器预检就会 404。
推荐做法是统一注册通配 OPTIONS 路由:
api := app.Party("/api")
api.Options("*", func(ctx iris.Context) { // 注意:这里 * 是路径通配符,不是 CORS 的 *
ctx.StatusCode(204)
})
api.Get("/users", GetUsersHandler)
api.Post("/users", CreateUsersHandler)
这样所有 /api/xxx 下的 OPTIONS 请求都会被捕获。不要依赖中间件“自动补全”预检路由——它不会。
容易被忽略的部署细节
开发时 localhost:3000 → localhost:8080 看似能跑通,但上线后常出问题:
- Nginx 反向代理时,如果没透传
Origin头(proxy_set_header Origin $http_origin;),Iris 拿不到原始源,Cors中间件会跳过设置 - 某些 CDN 或网关会缓存
OPTIONS响应,导致预检结果长期失效,建议加Cache-Control: no-store - 移动端 WebView(尤其是旧版 Android)对
Access-Control-Expose-Headers支持不一,需要测试实际能否读取自定义响应头
真正麻烦的从来不是写几行 header,而是确认每个环节——浏览器、代理、CDN、客户端代码——都按预期传递和解析这些字段。


















