简体   繁体   English

Golang Gin:中间件 CORS 不工作

[英]Golang Gin: Middleware with CORS not working

I've got a POST request from my frontend app to my backend app written in Go using Gin.我有一个从我的前端应用程序到我的后端应用程序的 POST 请求,该请求是使用 Gin 在 Go 中编写的。 I was getting an error saying:我收到一条错误消息:

"No 'Access-Control-Allow-Origin' header is present on the requested resource" “请求的资源上不存在‘Access-Control-Allow-Origin’header”

so that pointed me to implement CORS in my backend app.这样我就可以在我的后端应用程序中实现 CORS。 So I did by using "github.com/gin-contrib/cors" :所以我通过使用"github.com/gin-contrib/cors"做了:

web.go : web.go :

func NewApp() *App {

    db := SetUpDB()
    router := gin.Default()

    router.Use(cors.New(cors.Config{
        //AllowOrigins:    []string{"http://localhost:3000", "http://127.0.0.1:3000"},
        AllowMethods:    []string{"PUT", "POST", "GET", "OPTIONS","DELETE"},
        AllowHeaders:    []string{"Origin"},
        AllowAllOrigins: true,
        //ExposeHeaders:    []string{"Content-Length"},
        AllowCredentials: true,
        MaxAge:           12 * time.Hour,
    }))

    return &App{
        Db:     db,
        Router: router,
    }
}

and in main.go I've got:main.go中我有:

app := core.NewApp()

    //app.Router.Use(CORS())

    defer func() {
        app.Db.Close()
        log.Printf("core: database stopping")
    }()

    app.Router.Use(func(c *gin.Context) {
        c.Set("db", app.Db)
    })

    app.Router.GET("/", func(ctx *gin.Context) {
        ctx.JSON(http.StatusOK, gin.H{"data": "welcome TEST"})
    })

    // Initialize all api routes
    routes.InitializeRoutes(app.Router.Group("/api/v1"))

as you can see I only set PUT in AllowMethods with the intention of testing CORS was actually working.如您所见,我只在AllowMethods中设置了PUT ,目的是测试 CORS 是否确实有效。 By allowing only PUT I was expecting no methods other than PUT were allowed but I was wrong.通过只允许PUT ,我期望除了PUT之外没有其他方法被允许,但我错了。 I've performed a GET request from my frontend app and it goes through (it returns data), this leads me to think than the CORS implementation is not being picked up.我已经从我的前端应用程序执行了一个GET请求并且它通过了(它返回数据),这让我想到 CORS 实现没有被拾取。

While browsing around, I've found people not using the package "github.com/gin-contrib/cors" but creating their own middleware:在四处浏览时,我发现人们没有使用 package "github.com/gin-contrib/cors" ,而是创建了自己的中间件:

func CORS() gin.HandlerFunc {
    return func(c *gin.Context) {

        fmt.Println(c.Request.Header)
        c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
        c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
        c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, Origin, Cache-Control, X-Requested-With")
        //c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT, DELETE")
        c.Writer.Header().Set("Access-Control-Allow-Methods", "PUT, DELETE")

        if c.Request.Method == "OPTIONS" {
            c.AbortWithStatus(204)
            return
        }

        c.Next()
    }
}

and then:然后:

func NewApp() *App {

    db := SetUpDB()
    router := gin.Default()

    router.Use(CORS())

    return &App{
        Db:     db,
        Router: router,
    }
}

I tried this as well with no luck.我也试过这个,但没有运气。 Same results are coming back.同样的结果又回来了。

Furthermore, when I perform the GET and print the method in my backend ( c.Request.Method ) the result is GET .此外,当我执行GET并在我的后端 ( c.Request.Method ) 中打印方法时,结果是GET But when I perform a POST and print the method I'm getting OPTIONS但是当我执行POST并打印方法时,我得到了OPTIONS

What am I missing?我错过了什么? Why router is not using the provided middleware?为什么router不使用提供的中间件?

The Access-Control-Allow-Methods header is only checked for CORS requests that cannot result from a Javascript-less HTML page (so-called non-simple requests). Access-Control-Allow-Methods header 仅检查 CORS 请求,这些请求不能来自无 Javascript HTML 页面(所谓的非简单请求)。 For simple requests such as GET with only standard headers, only the Access-Control-Allow-Origin header is checked and the Access-Control-Allow-Methods header plays no role.对于只有标准标头的 GET 等简单请求,仅检查Access-Control-Allow-Origin header,而Access-Control-Allow-Methods header 不起作用。

There are two pieces to this question:这个问题有两部分:

  1. The first one was indicated above by Heiko: Get is a simple request so the result is always gonna be returned for these kind of requests. Heiko 在上面指出了第一个:Get 是一个简单的请求,因此对于这类请求,总是会返回结果。

  2. Now, after testing back my POST , I was still getting errors.现在,在测试我的POST之后,我仍然遇到错误。 I had checked over and over the CORS config, changing things here and there just to find out that the routes for Category were define such as:我一遍又一遍地检查了 CORS 配置,在这里和那里更改内容只是为了发现类别的路由定义如下:

categoryRouter.POST("/", controllers.CreateNewCategory)
categoryRouter.GET("/", controllers.ListAllCategories)

as you can see there is a trailing / which was causing my request to be redirected and an error to be returned since the url used for the request was http://127.0.0.1:8080/api/v1/categories .如您所见,尾随/导致我的请求被重定向并返回错误,因为用于该请求的 url 是http://127.0.0.1:8080/api/v1/categories I updated the routes to be:我将路线更新为:

categoryRouter.POST("", controllers.CreateNewCategory)
categoryRouter.GET("", controllers.ListAllCategories)

and now it is working as expected.现在它按预期工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM