英文:
failed to access subdomain from main domain: No 'Access-Control-Allow-Origin'
问题
版本
go 1.17
github.com/gin-contrib/cors v1.3.1
github.com/gin-gonic/gin v1.7.7
问题
我在子域中运行gin REST API服务器。
放置在主域中的React应用程序使用GET方法和POST方法访问API服务器,但是出现了跨域策略错误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.
。
在网络搜索中,我找到了相同的问题和一些解决方案,但在我的情况下它们都不起作用。
代码
所有这些程序都出现了相同的错误。
情况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)
}
}
情况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)
}
}
情况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)
}
}
终端预检请求
> 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 -->
解决方案
这是由于aws_lb_target_group
的设置引起的。
我在目标组中设置了HTTPS协议,尽管我只给Route 53和ALB提供了ACM证书。
我将HTTPS替换为HTTP,现在它可以工作了。
英文:
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.
答案1
得分: 3
诊断此类问题的第一步是直接在Chrome DevTools中检查预检请求。
注意事项:
- 如果预检响应被缓存,请勾选“禁用缓存”。
- 找到类型为“preflight”的请求。
下一步是将预检请求复制为curl
命令(右键单击请求,在上下文菜单中选择“复制”->“复制为cURL”),并使用curl
工具直接测试请求(记得修改命令以添加-i
选项以打印响应头)。
看起来你在生产环境中遇到了这个问题,可能是浏览器和你的服务之间的反向代理默认阻止了Access-Control-Allow-Origin
头。尝试直接将预检请求发送到你的服务,看看是否有任何不同。
更新(提供预检响应后):
事实证明,这根本不是CORS问题。请求失败,状态码为502 Bad Gateway
。应用程序没有正确部署。
顺便说一下,我已经测试了Case 1,它可以工作。
英文:
The good first step to diagnose such kind of problem is to check the preflight request in the Chrome DevTools directly.
Notes:
- Check
Disable cache
in case that the preflight response is cached. - 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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论