Revel跨域必须启动时配置app.conf并注册Interceptor,不能靠中间件临时加头;需开启http.cors.enabled=true、精确设置allowedorigins、谨慎使用allowcredentials、显式声明exposedheaders,并确保路由匹配预检请求。

CORS 配置必须在 Revel 启动时注册,不能靠中间件临时加响应头
Revel 框架本身不内置 CORS 中间件,也不自动识别 @CrossOrigin 这类 Spring 风格注解。它的跨域控制依赖于显式配置 app.conf 和自定义拦截器(interceptor),否则浏览器会直接拦截请求,连后端日志都看不到。
修改 app.conf 开启基础跨域支持
Revel 的跨域能力不是开箱即用的,必须手动打开 http.cors.enabled = true,否则所有跨域请求都会被静默拒绝。
-
http.cors.enabled = true是开关,缺省为false -
http.cors.allowedorigins = ["http://localhost:8080", "https://myapp.com"]必须写具体域名,不能填*(尤其当你启用http.cors.allowcredentials = true时) -
http.cors.allowcredentials = true表示允许前端携带 Cookie 或 Authorization 头,但此时allowedorigins严禁用通配符 -
http.cors.exposedheaders = ["X-Total-Count", "X-Request-ID"]若前端需读取自定义响应头,必须在此显式声明
用 Interceptor 手动注入 CORS 响应头(更灵活)
当 app.conf 配置无法满足动态 origin 判断(比如白名单存在数据库里),就得写代码控制。Revel 的 Interceptor 是唯一能统一干预响应头的地方,且必须在 INIT 阶段注册,晚了就无效。
- 在
app/init.go的init()函数中调用revel.Interceptors.Insert(&CorsInterceptor{}, revel.BEFORE) - 拦截器里不要直接写
c.Response.Out.Header().Set(),要用c.Result = revel.Result方式返回,否则可能被后续拦截器覆盖 - 对 OPTIONS 预检请求必须单独处理:检查
c.Request.Method == "OPTIONS",然后立即return revel.NOP并设置200 OK状态码和必要头 - 实际响应头应包含:
Access-Control-Allow-Origin、Access-Control-Allow-Methods、Access-Control-Allow-Headers、Access-Control-Max-Age
常见错误:Revel 路由匹配失败导致 CORS 不生效
Revel 的路由是严格按路径前缀匹配的,如果前端请求的是 /api/v1/users,而你只在 routes 文件里写了 GET /users,那请求根本进不到框架层,CORS 配置自然不会触发——浏览器报错仍显示 CORS policy,但其实是 404。
- 确保
conf/routes中有对应路径的定义,哪怕只是空 handler - 避免用正则路由(
:id)漏掉 OPTIONS 请求;预检请求的 path 和 method 必须能被某条 route 捕获 - 检查
revel.AppConfig.StringDefault("mode", "dev")是否为prod:某些生产模式下,静态文件路由优先级更高,可能吞掉 API 请求 - 用
curl -I -X OPTIONS http://localhost:9000/api/v1/users测试预检是否返回 200 + 正确头,而不是 405 或 404
Revel 的跨域逻辑藏在启动初始化和拦截器链里,不看源码很容易以为改了配置就完事。最常被忽略的是:预检请求必须被路由捕获、allowcredentials 和 allowedorigins 的互斥约束、以及 exposedheaders 不声明就前端拿不到。这些点没对齐,前端永远卡在红字报错。


















