为了账号安全,请及时绑定邮箱和手机立即绑定

Angular 前端 POST 到 Golang 后端方法不允许并被 CORS 策略阻止

Angular 前端 POST 到 Golang 后端方法不允许并被 CORS 策略阻止

Go
慕田峪9158850 2023-06-01 16:27:06
我正在尝试从我的 Angular 前端向我的 Golang 后端发出发布请求,两者都由同一台机器提供。我不断得到:OPTIONS http://localhost:12345/anteroom 405 (Method Not Allowed)和Access to XMLHttpRequest at 'http://localhost:12345/anteroom' from origin 'http://localhost:4200' 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.Golang 后端,使用 Gorilla mux 路由器:func main() {    router := mux.NewRouter()    router.HandleFunc("/anteroom", anteroom).Methods("POST")    log.Fatal(http.ListenAndServe(":12345", router))}func anteroom(res http.ResponseWriter, req *http.Request) {    res.Header().Set("Access-Control-Allow-Origin", "*")    // *Edit 17 Jan 19 12.44pm*: Billy, user268396, and Peter suggest that OPTIONS should be added. As mentioned below, I've already tried that.    res.Header().Set("Access-Control-Allow-Methods", "POST")    res.Header().Set("Content-Type", "application/json")    // Put it into a struct variable and print a bit of it.    _ = json.NewDecoder(req.Body).Decode(&member)    fmt.Println(member.ID)}
查看完整描述

3 回答

?
倚天杖

TA贡献1828条经验 获得超3个赞

这不是你CORS在后端的做法。您的后端需要侦听 HTTPOPTIONS类型的请求并将 CORS 标头发送到那里。

控制流程大致是:

  1. 你在前端请求一些东西

  2. 浏览器判断:呃哦,这需要 CORS

  3. 浏览器首先对请求的资源进行OPTIONS请求,协商CORS

  4. 根据结果,任一浏览器都会向您的前端抛出错误

  5. 或者它继续您的前端发出的实际请求。

  6. 从现在开始一切正常

  7. 当浏览器获得您的实际 API 回调的结果时,它会过滤掉未在步骤 3 和 4 中列入白名单/协商的内容。

  8. 作为 HTTP 调用的结果,它将可能被审查的结果呈现给前端。


查看完整回答
反对 回复 2023-06-01
?
潇潇雨雨

TA贡献1833条经验 获得超4个赞

问题的解决在很大程度上要感谢所有帮助我意识到我没有正确执行 CORS 的人。基本上,有两个问题:1. 我不知道在后端正确设置标头,以及 2. 我没有正确格式化我的 JSON 数据。

通常,它很简单:当你想要请求某些东西时,浏览器会根据你已有的内容设置适当的标头,然后将请求发送出去。服务器响应。

但是,假设您在同一域的后端和前端有一个 API POST 端点(我想我们大多数人都在开发,但可能不在生产中),并且您正在使用 application/x 以外的任何东西-www-form-urlencoded,multipart/form-data,还有text/plain,那就有点不一样了。就我而言,我正在使用 application/json。所以,它看起来像这样:

  1. 浏览器使用 OPTIONS 方法发送请求,询问允许使用哪些方法和内容类型以及其他内容。这称为预检请求。它还没有发送我的 JSON 对象。

  2. 服务器响应预检请求。

为了让服务器响应允许的内容,我们需要正确设置后端以允许 Access-Control-Allow-Methods 中的 OPTIONS 方法,如果您像我一样使用 Gorilla mux,请记住也允许它进入router.HandleFunc()

因为我们的前后端在同一个域(http://localhost),最简单的做法是将 Access-Control-Allow-Origin 设置为“*”。但是,根据我们的需要,我们可能不想在生产中这样做,因为 * 意味着全世界及其他地方都可以发送请求。

因为我要接收JSON,所以我在后端也设置了Content-Type为application/json。这是我问题的另一半。长话短说,无论对其他人有用的是什么,出于某种原因我仍然必须应用JSON.stringify()到我的原始 JSON 数据。然后它完美地工作。

  1. 一旦浏览器收到允许的 OPTIONS,它就会过滤掉不允许的内容,并发回仅包含适当数据的请求。在我的例子中,这将是 JSON 对象。

就是这样。


查看完整回答
反对 回复 2023-06-01
?
慕田峪7331174

TA贡献1828条经验 获得超13个赞

“ Access-Control-Allow-Origin”表示您允许向该服务器发出请求的来源。

它可以是以下形式:

Access-Control-Allow-Methods当你想从 CORS 发布数据时,“ ” 应该是 []string("POST", "OPTION") 。

说到golang,看godoc https://golang.org/pkg/net/http/#Header

type Header map[string][]string

而且我总是建议使用Header.Add()instead ofHeader.Set()除非你确切地知道你在做什么。因为 header 中的每个值总是 []string。

所以应该是

  res.Header().Add("Access-Control-Allow-Origin", "*")
    res.Header().Add("Access-Control-Allow-Methods", "POST")
    res.Header().Add("Access-Control-Allow-Methods", "OPTION")
    res.Header().Add("Content-Type", "application/json")


查看完整回答
反对 回复 2023-06-01
  • 3 回答
  • 0 关注
  • 118 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信