CORS 跨域:中间件配置要点
前后端分离后,浏览器页面(http://web.example.com)直接请求 API(http://api.example.com)会触发跨域限制。GoFrame v2 的跨域能力由 ghttp.Response 上的 CORS 方法与路由中间件配合完成,官方文档“CORS 跨域处理”章节给出了完整配置范式。
基本概念
- CORS(跨域资源共享)是 W3C 标准:服务端通过响应头声明“允许哪些来源、哪些方法/请求头、是否允许携带凭证”。
- ghttp 用
CORSOptions对象承载这些选项,Response提供CORS(options)、CORSDefault()、DefaultCORSOptions()、CORSAllowedOrigin(options)方法。 OPTIONS预检请求由 Server 按规范自动响应,前提是请求走到了带 CORS 头的路由。
通过中间件放行跨域
把跨域配置写成中间件挂在路由分组上,是最常见、最清晰的形态。先看“全放行”版:
package main
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
)
// 允许跨域请求的中间件:使用默认选项
func MiddlewareCORS(r *ghttp.Request) {
r.Response.CORSDefault()
r.Middleware.Next()
}
func main() {
s := g.Server()
s.Group("/api.v1", func(group *ghttp.RouterGroup) {
group.Middleware(MiddlewareCORS)
group.GET("/order", func(r *ghttp.Request) {
r.Response.Write("GET")
})
})
s.SetPort(8199)
s.Run()
}
group.Middleware 对分组下所有路由生效(含子路由),CORSDefault() 使用框架默认选项,适合开放接口或开发环境。
限制来源:只信任自己的域名
生产环境几乎都要收敛来源。利用 DefaultCORSOptions() 取出默认值后修改 AllowDomain,再交给 CORS:
func MiddlewareCORS(r *ghttp.Request) {
corsOptions := r.Response.DefaultCORSOptions()
corsOptions.AllowDomain = []string{"example.com", "admin.example.com"} // 白名单域名
if !r.Response.CORSAllowedOrigin(corsOptions) {
r.Response.WriteStatus(http.StatusForbidden) // 来源不在白名单,直接拒绝
return
}
r.Response.CORS(corsOptions)
r.Middleware.Next()
}
CORSAllowedOrigin 在真正放行前先校验当前请求的 Origin,来源不合法时业务逻辑根本不会执行,比“先放行再判断”更省资源也更安全。
注意点
- 携带 Cookie 的跨域请求需要
AllowCredentials配合精确的AllowOrigin(不能简单用通配*),前端也要设置withCredentials。 - 不要对全站一刀切放开
*:把 CORS 中间件只挂到需要跨域的 API 分组即可。 - 跨域也常与 WebSocket 场景相关,官方说明允许 WebSocket 跨域同样通过 CORS 方式处理;但 WebSocket 本身的来源/鉴权校验仍需业务层自己完成。
- 若用规范路由(
group.Bind),同样把 CORS 中间件挂到分组上,文档与跨域可并存。
小结
CORS 的落地公式:中间件 + 分组路由 + CORSOptions。开发期用 CORSDefault() 快速放行,生产期用 AllowDomain 白名单并用 CORSAllowedOrigin 提前拦截。默认选项字段(AllowMethods/AllowHeaders/MaxAge 等)可继续按需调整,细节以官方文档 goframe.org 为准。