You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Gin框架gin-contrib/cors中间件与Group()搭配失效问题

Gin路由组中gin-contrib/cors中间件失效的解决方案

问题现象

  • 直接在Gin根路由器上使用gin-contrib/cors中间件时,所有路由的CORS响应头正常返回
  • 用r.Group("/api")创建路由组后,组内所有路由均丢失access-control-allow-origin响应头,中间件完全失效
  • 手动设置响应头或自定义极简CORS中间件(如下)可正常工作
func CORS() gin.HandlerFunc {
    return func(ctx *gin.Context) {
        ctx.Header("access-control-allow-origin", "*")
        ctx.Next()
    }
}
  • 尝试过在根路由器、路由组单独或同时挂载cors.Default(),均无效果;仅将路由直接绑定到根路由器时中间件才生效

原因分析

cors.Default()的默认配置对预检请求(OPTIONS)的路径匹配逻辑存在局限性,当请求路由属于分组路径时,中间件无法正确匹配并处理预检请求,导致CORS头未被设置。而自定义中间件因为逻辑简单,直接对所有请求设置头,不受路由组匹配规则影响。

解决方案

放弃使用cors.Default(),改用自定义CORS配置,明确指定允许的源、方法、请求头,确保中间件能覆盖路由组内的所有请求(包括预检请求)。

方案1:根路由器挂载自定义CORS中间件

package main

import (
	"github.com/gin-contrib/cors"
	"github.com/gin-gonic/gin"
	"time"
)

func main() {
	r := gin.Default()

	// 自定义CORS配置,生产环境建议将AllowOrigins替换为具体信任域名
	corsConfig := cors.Config{
		AllowOrigins:     []string{"*"},
		AllowMethods:     []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
		AllowHeaders:     []string{"Origin", "Content-Type", "Authorization"},
		ExposeHeaders:    []string{"Content-Length"},
		AllowCredentials: true,
		MaxAge:           12 * time.Hour,
	}

	// 根路由器应用中间件,所有路由组自动继承
	r.Use(cors.New(corsConfig))

	apiRouter := r.Group("/api")
	apiRouter.GET("/record", func(ctx *gin.Context) {
		ctx.JSON(200, gin.H{"status": "ok", "data": "record data"})
	})

	r.Run("127.0.0.1:3000")
}

方案2:仅在路由组挂载自定义CORS中间件

package main

import (
	"github.com/gin-contrib/cors"
	"github.com/gin-gonic/gin"
	"time"
)

func main() {
	r := gin.Default()

	apiRouter := r.Group("/api")

	// 为目标路由组单独配置CORS
	corsConfig := cors.Config{
		AllowOrigins:     []string{"*"},
		AllowMethods:     []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
		AllowHeaders:     []string{"Origin", "Content-Type", "Authorization"},
		AllowCredentials: true,
		MaxAge:           12 * time.Hour,
	}
	apiRouter.Use(cors.New(corsConfig))

	apiRouter.GET("/record", func(ctx *gin.Context) {
		ctx.JSON(200, gin.H{"status": "ok", "data": "record data"})
	})

	r.Run("127.0.0.1:3000")
}

验证方式

用curl发送预检请求测试:

curl -X OPTIONS http://127.0.0.1:3000/api/record \
-H "Origin: http://your-frontend-domain.com" \
-H "Access-Control-Request-Method: GET"

查看响应头,确认access-control-allow-origin已正确设置。

内容的提问来源于stack exchange,提问作者Zhou Xudong

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 06:46:00