Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

failed to access subdomain from main domain: No 'Access-Control-Allow-Origin'

Tags:

cors

go

go-gin

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..

On web search, I found the same issue and some solutions, but they didn't work in my case.

Code

All of these programs got the same error.

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.

like image 902
Asuha Avatar asked Jan 18 '26 23:01

Asuha


1 Answers

The good first step to diagnose such kind of problem is to check the preflight request in the Chrome DevTools directly.

Chrome DevTools screenshot

Notes:

  1. Check Disable cache in case that the preflight response is cached.
  2. Find the request whose type is preflight.

The next step is to copy the preflight request as curl command (right click on the request, select Copy->Copy as cURL in the context menu) and test the request with the curl tool directly (remember to modify the command to add the -i option to print the response headers).

It seems that you encountered the issue on a production environment, it's possible that a reverse proxy sitting between the browser and your service blocks the Access-Control-Allow-Origin header by default. Try to send the preflight request directly to your service and see if there is anything different.

Update (after the preflight response is provided):

It turns out that this is not a CORS issue at all. The request failed with the status code 502 Bad Gateway. The application is not deployed correctly.


BTW, I have tested Case 1 and it works:

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
like image 148
Zeke Lu Avatar answered Jan 20 '26 21:01

Zeke Lu