英文:
multiple CORS values being rejected in Go gin api
问题
在我的Go API中,我正在使用gin,并且在我的Access-Control-Allow-Origin
头部中设置了一个值。如果我设置了多个值,我的React UI会抛出一个错误,内容为The Access-Control-Allow-Origin header contains multiple values 'http://value1, http://value2', but only one is allowed...
。我需要设置多个值。我该如何做?
这个API是一个反向代理,以下是相关的代码:
func proxy(c *gin.Context) {
var remote = "myUrl"
proxy := httputil.NewSingleHostReverseProxy(remote)
proxy.Director = func(req *http.Request) {
req.Header.Set("Authorization", "My Auth Values")
req.Host = remote.Host
req.URL.Scheme = remote.Scheme
req.URL.Host = remote.Host
}
proxy.ModifyResponse = addCustomHeader
proxy.ServeHTTP(c.Writer, c.Request)
}
func addCustomHeader(r *http.Response) error {
r.Header["Access-Control-Allow-Origin"] = []string{"value1;"}
return nil
}
英文:
In my Go API, I'm using gin, and I have one value set in my Access-Control-Allow-Origin
header. If I have more than one, my react UI throws an error to the effect of The Access-Control-Allow-Origin header contains multiple values 'http://value1, http://value2', but only one is allowed...
. I need to set multiple values. How do I do this?
The API is a reverse proxy, and here's the relevant code:
func proxy(c *gin.Context) {
var remote = "myUrl"
proxy := httputil.NewSingleHostReverseProxy(remote)
proxy.Director = func(req *http.Request) {
req.Header.Set("Authorization", "My Auth Values")
req.Host = remote.Host
req.URL.Scheme = remote.Scheme
req.URL.Host = remote.Host
}
proxy.ModifyResponse = addCustomHeader
proxy.ServeHTTP(c.Writer, c.Request)
}
func addCustomHeader(r *http.Response) error {
r.Header["Access-Control-Allow-Origin"] = []string{"value1"}
return nil
}
</details>
# 答案1
**得分**: 2
CORS头部只能包含一个值。如果你想要实现自己的CORS中间件,你需要绕过这个限制。
一个简单的CORS中间件会添加`Access-Control-Allow-Origin`头部,其值为传入请求的特定地址,通常从`Referer`或`Origin`头部获取。通常,你会先将这个地址与一个列表或映射进行匹配,以查看它是否在你的"允许列表"中。如果是的话,请求的地址就会被添加为允许的来源(作为一个单独的值)。
一个简单的示例可能如下所示:
```go
allowList := map[string]bool{
"https://www.google.com": true,
"https://www.yahoo.com": true,
}
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if origin := r.Header.Get("Origin"); allowList[origin] {
w.Header().Set("Access-Control-Allow-Origin", origin)
}
})
由于你正在使用反向代理,你可以从响应中访问请求。
mod := func(allowList map[string]bool) func(r *http.Response) error {
return func(r *http.Response) error {
if origin := r.Request.Header.Get("Origin"); allowList[origin] {
r.Header.Set("Access-Control-Allow-Origin", origin)
}
return nil
}
}
proxy := &httputil.ReverseProxy{
Director: func(r *http.Request) {
r.URL.Scheme = "https"
r.URL.Host = "go.dev"
r.Host = r.URL.Host
},
ModifyResponse: mod(allowList),
}
英文:
A CORS header can only contain a single value. If you want to implement your own CORS middleware, you need to work around that fact.
A simple CORS middleware will add the Access-Control-Allow-Origin
header with the value of the specific address of the incoming request, usually taken from the Referer
or Origin
header. Typically, you match this against a list or map first, to see if it's in your allow list. If so, then the address of the request is added as allowed origin (as a single value).
A simple example could look like this
allowList := map[string]bool{
"https://www.google.com": true,
"https://www.yahoo.com": true,
}
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if origin := r.Header.Get("Origin"); allowList[origin] {
w.Header().Set("Access-Control-Allow-Origin", origin)
}
})
Since you are using the reverse proxy, you can access the request from the response.
mod := func(allowList map[string]bool) func(r *http.Response) error {
return func(r *http.Response) error {
if origin := r.Request.Header.Get("Origin"); allowList[origin] {
r.Header.Set("Access-Control-Allow-Origin", origin)
}
return nil
}
}
proxy := &httputil.ReverseProxy{
Director: func(r *http.Request) {
r.URL.Scheme = "https"
r.URL.Host = "go.dev"
r.Host = r.URL.Host
},
ModifyResponse: mod(allowList),
}
答案2
得分: 1
每个传入请求只需要一个值。通常的做法是在服务器上配置受信任的来源,例如:
- trustedOrigins: [https://www.domain1.com, https://www.domain2.com]
然后检查由所有现代浏览器发送的origin
头的运行时值。如果这是一个受信任的来源,那么添加CORS头:
- Access-Control-Allow-Origin: https://www.domain2.com
可以使用通配符,但这不被推荐,而且如果您还使用带有cookie的凭证请求(例如),它也无法按预期工作。
英文:
You only need a single value for each incoming request. The usual technique is to configure trusted origins on the server, eg:
- trustedOrigins: [https://www.domain1.com, https://www.domain2.com]
Then check the runtime value of the origin
header, which is sent by all modern browsers. If this is a trusted origin then add CORS headers:
- Access-Control-Allow-Origin: https://www.domain2.com
A wildcard could be used but that is not recommended and also will not work as intended if you are also using credentialed requests (eg those with cookies).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论