英文:
CORS issue - React/Axios Frontend and Golang Backend
问题
我有一个用Golang编写的后端REST API服务。我在React前端中使用axios来向API发送POST请求。尽管我认为我已经在前端和后端都启用了CORS,但浏览器仍然抛出以下错误:
由于预检响应的Access-Control-Allow-Headers不允许请求头字段access-control-allow-origin,因此已阻止从源'http://localhost:3000'访问'http://localhost:8080/winERC20'的XMLHttpRequest。
请问有人能提供解决方法吗?
main.go
func main() {
fmt.Println("Server is serving at http://localhost:8080/")
// 初始化mux路由器
router := mux.NewRouter()
router.HandleFunc("/", helloHandler)
router.HandleFunc("/matchingABI", api.MatchingContractABI)
router.HandleFunc("/winERC20", api.WinERC20_controller).Methods("POST", "OPTIONS")
log.Fatal(http.ListenAndServe(":8080", router))
}
api.go
func WinERC20_controller(w http.ResponseWriter, r *http.Request) {
enableCors(&w)
if r.Method == "OPTIONS" {
w.WriteHeader(http.StatusOK)
return
}
// 尝试将请求体解码为结构体。如果有错误,向客户端返回错误消息和400状态码。
var p winERC20_RequestBody
err := json.NewDecoder(r.Body).Decode(&p)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
...
w.Header().Set("Content-Type", "application/json")
resp := make(map[string]string)
resp["message"] = "Success"
jsonResp, err := json.Marshal(resp)
if err != nil {
log.Fatalf("JSON编组时发生错误。错误:%s", err)
}
w.Write(jsonResp)
}
func enableCors(w *http.ResponseWriter) {
header := (*w).Header()
header.Add("Access-Control-Allow-Origin", "*")
header.Add("Access-Control-Allow-Methods", "DELETE, POST, GET, OPTIONS")
header.Add("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With")
}
frontend.js
grantERC20(){
// 将ERC20转移到玩家账户
let url = 'http://localhost:8080/winERC20'
let config = {
headers: {
"Content-Type": "application/json",
'Access-Control-Allow-Origin': '*',
}
}
let data = {
"PublicAddress" : this.props.account,
"Amount": this.props.score
}
axios.post(url, data, config)
.then(
(response) => {console.log(response)},
(error) => {console.log(error);}
);
}
componentDidMount () {
this.grantERC20()
}
以上是您提供的代码的翻译。
英文:
I have a backend REST API service written in Golang. I used axios in the React frontend to POST to the API. Even though I think I have enabled the CORS for both the frontend and backend, the browser still throws this error:
> Access to XMLHttpRequest at 'http://localhost:8080/winERC20' from origin 'http://localhost:3000' has been blocked by CORS policy: Request header field access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response.
Can anyone please suggest what I should do to solve this?
main.go
func main() {
fmt.Println("Server is serving at http://localhost:8080/")
// Init the mux router
router := mux.NewRouter()
router.HandleFunc("/", helloHandler)
router.HandleFunc("/matchingABI", api.MatchingContractABI)
router.HandleFunc("/winERC20", api.WinERC20_controller).Methods("POST", "OPTIONS")
log.Fatal(http.ListenAndServe(":8080", router))
}
api.go
func WinERC20_controller(w http.ResponseWriter, r *http.Request) {
enableCors(&w)
if r.Method == "OPTIONS" {
w.WriteHeader(http.StatusOK)
return
}
// Try to decode the request body into the struct. If there is an error,
// respond to the client with the error message and a 400 status code.
var p winERC20_RequestBody
err := json.NewDecoder(r.Body).Decode(&p)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
...
w.Header().Set("Content-Type", "application/json")
resp := make(map[string]string)
resp["message"] = "Success"
jsonResp, err := json.Marshal(resp)
if err != nil {
log.Fatalf("Error happened in JSON marshal. Err: %s", err)
}
w.Write(jsonResp)
}
func enableCors(w *http.ResponseWriter) {
header := (*w).Header()
header.Add("Access-Control-Allow-Origin", "*")
header.Add("Access-Control-Allow-Methods", "DELETE, POST, GET, OPTIONS")
header.Add("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With")
}
frontend.js
grantERC20(){
// Transfer ERC20 to the player
let url = 'http://localhost:8080/winERC20'
let config = {
headers: {
"Content-Type": "application/json",
'Access-Control-Allow-Origin': '*',
}
}
let data = {
"PublicAddress" : this.props.account,
"Amount": this.props.score
}
axios.post(url, data, config)
.then(
(response) => {console.log(response)},
(error) => {console.log(error);}
);
}
componentDidMount () {
this.grantERC20()
}
答案1
得分: 1
为什么在你的客户端代码中,你要在请求中添加一个名为Access-Control-Allow-Origin
的头部?这个头部是一个_响应_头部,而不是一个_请求_头部。此外,由于你的CORS配置不允许这样的请求头,CORS预检将会失败:
header.Add("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With")
解决方法很简单:只需从你的请求中删除Access-Control-Allow-Origin
头部。
此外,你应该考虑使用一些经过验证的CORS中间件,而不是手动实现CORS(这样容易出错),比如https://github.com/rs/cors。
英文:
Why, in your client-side code, are you adding a header named Access-Control-Allow-Origin
to your request? That header is a response header, not a request header. Moreover, CORS preflight is bound to fail because your CORS configuration doesn't allow such a request header:
header.Add("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With")
The remedy is simple: just drop that Access-Control-Allow-Origin
header from your request.
Besides, instead of implementing CORS "manually" (which is error-prone), you should consider relying on some proven CORS middleware, such as https://github.com/rs/cors.
答案2
得分: -1
TL;DR: 在React前端中使用Fetch
替代Axios
,并将后端API的URL(http://localhost:8080)添加为package.json
中的proxy
。
我遇到了相同的问题,在花了一整天的时间尝试各种可用的解决方案后,我通过将Axios
调用替换为fetch
来解决了这个问题。
在Frontend.js中:
await fetch("http://localhost:8080/winERC20", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: new URLSearchParams(data),
});
在Package.json中:
"proxy":"http://localhost:8080",
编辑:我已经安装了CORS扩展程序。
英文:
TL;DR: Use Fetch
instead of Axios
in the React Frontend and add the backend API URL (http://localhost:8080) as proxy
in package.json
.
I faced the same issue, and after spending a day into it, trying each and every solution available, I came to a fix by replacing the Axios
call with fetch
.
In Frontend.js:
await fetch("http://localhost:8080/winERC20", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: new URLSearchParams(data),
});
In Package.json:
"proxy":"http://localhost:8080",
Edit: I had installed the CORS extension
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论