versions

go 1.17
github.com/gin-contrib/cors v1.3.1
github.com/gin-gonic/gin v1.7.7

problem

I run gin REST API server in my subdomain.
React app placed in main domain access to the API server with GET method and POST method, but get cors policy error Access to XMLHttpRequest at 'https://<subdomain>.<domain>.xxx/api/v1/users' from origin 'https://<domain>.xxx' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource..

在网络搜索中,我发现了同样的问题和一些解决方案,但它们在我的情况下不起作用.

Code

所有这些程序都收到了相同的错误.

case 1

package gateway

import (
    "log"

    "github.com/gin-contrib/cors"
    "github.com/gin-gonic/gin"
)

func RunServer() {
    r := gin.Default()
    r.Use(cors.Default())
    api := r.Group("/api")
    v1 := api.Group("/v1")
    userRouters(v1)
    err := r.Run()
    if err != nil {
        log.Printf("failed to run gateway: %v", err)
    }
}

case 2

package gateway

import (
    "log"
    "time"

    "github.com/gin-contrib/cors"
    "github.com/gin-gonic/gin"
)

func RunServer() {
    r := gin.Default()
    r.Use(cors.New(cors.Config{
        AllowOrigins:     []string{"*"},
        AllowMethods:     []string{"GET", "POST", "PUT", "DELETE"},
        AllowHeaders:     []string{"Content-Type"},
        AllowCredentials: false,
        MaxAge:           12 * time.Hour,
    }))
    api := r.Group("/api")
    v1 := api.Group("/v1")
    userRouters(v1)
    err := r.Run()
    if err != nil {
        log.Printf("failed to run gateway: %v", err)
    }
}

case 3

Missing Access-Control-Allow-Origin in response header. · Issue #29 · gin-contrib/cors

package gateway

import (
    "log"

    "github.com/gin-gonic/gin"
)

func CORS() gin.HandlerFunc {
    return func(c *gin.Context) {
        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")

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

        c.Next()
    }
}

func RunServer() {
    r := gin.Default()
    r.Use(CORS())
    api := r.Group("/api")
    v1 := api.Group("/v1")
    userRouters(v1)
    err := r.Run()
    if err != nil {
        log.Printf("failed to run gateway: %v", err)
    }
}

preflight from terminal

> curl 'https://alb.skhole.club/api/v1/authz' \
  -X 'OPTIONS' \
  -H 'authority: alb.skhole.club' \
  -H 'accept: */*' \
  -H 'accept-language: ja,en-US;q=0.9,en;q=0.8' \
  -H 'access-control-request-headers: content-type' \
  -H 'access-control-request-method: POST' \
  -H 'cache-control: no-cache' \
  -H 'origin: https://skhole.club' \
  -H 'pragma: no-cache' \
  -H 'referer: https://skhole.club/' \
  -H 'sec-fetch-dest: empty' \
  -H 'sec-fetch-mode: cors' \
  -H 'sec-fetch-site: same-site' \
  -H 'user-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36' \
  --compressed -i
HTTP/2 502 
server: awselb/2.0
date: Wed, 05 Apr 2023 04:04:13 GMT
content-type: text/html
content-length: 524

<html>
<head><title>502 Bad Gateway</title></head>
<body>
<center><h1>502 Bad Gateway</h1></center>
</body>
</html>
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->

Solved

This is caused by the aws_lb_target_group settings.
I set the protocol HTTPS in the target group even though I gave ACM certificates to only Route 53 and ALB.
I replaced HTTPS with HTTP, and now it works.

推荐答案

诊断此类问题的第一步是直接在Chrome DevTool中判断印前判断请求.

Chrome DevTools screenshot

Notes:

  1. 如果已缓存印前判断响应,请选中Disable cache.
  2. 找到类型为preflight的请求.

下一步是将印前判断请求复制为curl命令(右击请求,在上下文菜单中 Select Copy->;Copy as cURL),并使用curl工具直接测试请求(记住修改命令以添加-i选项以打印响应头).

您似乎在生产环境中遇到了这个问题,可能是位于浏览器和服务之间的反向代理在默认情况下阻止了Access-Control-Allow-Origin标头.try 将印前判断请求直接发送到您的服务,并查看是否有不同之处.

Update(提供印前判断响应后):

事实证明,这根本不是CORS的问题.请求失败,状态代码为502 Bad Gateway.应用程序部署不正确.


顺便说一句,我测试了 case 1,它工作正常:

package main

import (
    "log"
    "net/http/httputil"

    "github.com/gin-contrib/cors"
    "github.com/gin-gonic/gin"
)

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

    r.Use(cors.Default())
    api := r.Group("/api")
    v1 := api.Group("/v1")
    v1.POST("users", func(ctx *gin.Context) {
        buf, err := httputil.DumpRequest(ctx.Request, true)
        if err != nil {
            log.Printf("failed to dump request: %v", err)
            return
        }

        log.Printf("%s", buf)
    })
    err := r.Run()
    if err != nil {
        log.Printf("failed to run gateway: %v", err)
    }
    r.Run()
}
$ curl 'http://localhost:8080/api/v1/users' \
  -X 'OPTIONS' \
  -H 'Accept: */*' \
  -H 'Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7,zh-TW;q=0.6' \
  -H 'Access-Control-Request-Headers: content-type' \
  -H 'Access-Control-Request-Method: POST' \
  -H 'Cache-Control: no-cache' \
  -H 'Connection: keep-alive' \
  -H 'Origin: http://127.0.0.1:5501' \
  -H 'Pragma: no-cache' \
  -H 'Referer: http://127.0.0.1:5501/' \
  -H 'Sec-Fetch-Dest: empty' \
  -H 'Sec-Fetch-Mode: cors' \
  -H 'Sec-Fetch-Site: cross-site' \
  -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36' \
  --compressed -i
HTTP/1.1 204 No Content
Access-Control-Allow-Headers: Origin,Content-Length,Content-Type
Access-Control-Allow-Methods: GET,POST,PUT,PATCH,DELETE,HEAD,OPTIONS
Access-Control-Allow-Origin: *
Access-Control-Max-Age: 43200
Date: Wed, 05 Apr 2023 03:50:06 GMT

Go相关问答推荐

JWT库返回及时无效的令牌有效

Golang Cososdb-gremlin连接

难以为多个平台添加Go Bazel构建选项

一种基于时间的Golang函数节制器

将类型定义为泛型类型实例化

如何使用Gio设置标题栏图标

如何使用gopher-lua定义一个Lua函数,该函数有一个预定义的表作为param,Lua脚本可以在其中访问该函数中的表?

Golang SDK for DynamoDB:ReturnValuesOnConditionCheckFailure在条件chcek失败发生时不返回条件的详细信息

无法获取RPC描述符

";无效的复制因子;融合Kafka Go客户端

Kusto Go API 从多个表查询

在 GoLang 中对自定义 struct 体数组进行排序

Golang 到 wasm 编译使用 tinygo.使用 wasmtime 执行

golang yaml 马歇尔网址

为什么在单独的 go routine 中需要 wg.Wait() 和 close() ?

从 Makefile 运行时权限被拒绝

github.com/rs/zerolog 字段的延迟判断

如何在测试中使用自定义标志(使用`testify/suite`)

使用 bolthold 3 条件进行 boltDB 查询

使用 xml.Name 将 xml 解组为 [] struct