【问题标题】:Axios request receiving a CORS error only when inside a callback/async function只有在回调/异步函数内部时,Axios 请求才会收到 CORS 错误
【发布时间】:2019-08-22 04:10:05
【问题描述】:

我正在将 VueJS 用于我正在构建的应用程序。我拥有的服务器是用 Golang 编写的,并且已设置为接受 CORS。在应用程序中,在我的一个组件searchBar 中,我已将其设置为在创建之前获取一些数据。

var searchBar = {
    prop: [...],
    data: function() {
        return { ... };
    },
    beforeCreate: function() {
        var searchBar = this;

        axios.request({
            url: '/graphql',
            method: 'post',
            data: {
                'query': '{courses{id, name}}'
            }
        })
        .then(function(response) {
            searchBar.courses = response.data.data.courses;
        });
    },
    methods: { ... },
    template: `...`
};

Axios 在这里完美运行。它得到我需要的数据。 searchBar 有一个按钮,它会导致它发出一个事件,然后由另一个组件searchResults 拾取。收到事件后,searchResults 将获取一些数据。

var searchResults = {
    data: function() {
        return { ... }
    },
    mounted: function() {
        var sr = this;

        this.$bus.$on('poll-server', function(payload) {
            var requestData = {
                url: '/graphql',
                method: 'post',
                data: { ... },
                ...
            };
            ...

            axios.request(requestData)
                 .then(function(response) {
                     console.log(response);
                 }
            );
        });
    },
    template: `...`
};

请注意,我的 Axios 请求调用现在位于回调函数中。执行此调用时,我收到一个 CORS 错误:

从源“http://127.0.0.1:8080”访问“http://127.0.0.1:9000/graphql”处的 XMLHttpRequest 已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查:没有“Access-Control-Allow-Origin”标头出现在请求的资源上。

我的服务器位于http://127.0.0.1:9000,客户端位于http://127.0.0.1:8080。这是第二次请求调用的OPTIONS请求的内容。

为了比较,这里是第一个请求调用的请求标头(有效!)。

我已经将我的 Golang 服务器设置为通过 go-chi/cors 支持 CORS。就是这样设置的。

router := chi.NewRouter()
...    
// Enable CORS.
cors := cors.New(cors.Options{
    AllowedOrigins:   []string{"*"},
    AllowedMethods:   []string{"POST", "OPTIONS"},
    AllowedHeaders:   []string{"Accept", "Authorization", "Content-Type", "X-CSRF-Token"},
    ExposedHeaders:   []string{"Link"},
    AllowCredentials: true,
    MaxAge:           300,
})

router.Use(
    render.SetContentType(render.ContentTypeJSON),
    middleware.Logger,
    middleware.DefaultCompress,
    middleware.StripSlashes,
    middleware.Recoverer,
    cors.Handler,
)

router.Post("/graphql", gqlServer.GraphQL())

return router, db

是什么导致了我遇到的错误以及如何解决?

【问题讨论】:

  • 不熟悉 go-chi/cors,但您确定 CORS 设置正确吗?您的第一个 POST 请求很可能是正确的,但对于第二个 GET 请求却不是。该错误清楚地显示第二个 API 上没有 Allowed Origin 标头。
  • @colminator 我不小心留下了第二个请求的详细信息。第二个请求也是POST 请求。
  • 请检查发送到服务器的OPTIONS 请求和响应,如果可以,请在此处发布
  • @BenYaakobi,我已将OPTIONS 请求添加到问题中。
  • @RejoanulAlam,是的,对于本地测试,不需要安全性。但是,最好将 dev/local 与生产中的内容相匹配。

标签: javascript go vue.js cors axios


【解决方案1】:

预计会出现此 CORS 错误。您使用的 CORS 插件会为您请求过滤。如果您查看允许的标头列表,您会发现它缺少您尝试在 axios 调用中发送的名为 snb-user-gps-location 的标头。

要么将该标头添加到允许列表中,要么不从前端发送。

【讨论】:

  • 哇!我不认为我的自定义标题丢失导致了我的问题。我已经确认这确实是解决方法。非常感谢!
  • 它还显示了发布与您的问题相关的所有代码的重要性,如果我没有查看您的请求的第一个屏幕截图,我永远不会发现这是您的错误,因为该屏幕截图是唯一提到此标题的地方
【解决方案2】:

我仍然怀疑 go-chi CORS 设置。我建议您手动设置 CORS。这并不难。此页面将获得基本设置:https://flaviocopes.com/golang-enable-cors/

如果这适用于您的嵌套 API 设置,那么我们可以向后确定 go-chi 配置问题。


更新:

我还将调查其他中间件步骤 - 注释掉所有非必要的步骤。

中间件处理程序通常检查r *http.Request 或将标头写入w http.ResponseWriter,然后最终处理程序将写入响应正文。但是在整个中间件链中,以下标头/正文写入流程应该看起来像这两个流程之一:

成功:

w.Header().Set(...) // headers
w.Write(...) // body

请注意,上述流程将发出隐式的 http 状态代码写入,以保持标题出现 first 和正文 second

w.Header().Set(...) // headers
w.WriteHeader(http.StatusOK) // implicit success http status code
w.Write(...) // body

失败:

如果报告运行时错误,流程应该是:

w.Header().Set(...) // headers
w.WriteHeader(http.StatusInternalServerError) // some unrecoverable error 
w.Write(...) // optional body

之所以提出这个问题,是因为我看到了 3 种类型的错误,这些错误会扰乱这个流程:

  • 错误的中间件处理程序在正文之后写入标头导致客户端混淆
  • 调用 http.Error 认为会停止 API 死机 - 而不是在 http.Error 之后立即返回并且确保不会调用后续中间件处理程序
  • 两次写入相同的标头。在后续处理程序中重写标头将导致客户端看到最后一个版本(从而破坏任何以前的版本)

因此,为了全面追踪事情,我会 log.Println 为您的 API 写入所有标头/正文,以确保上述流程正确且没有预期值被覆盖。

【讨论】:

  • 双 API?我一定把你弄糊涂了。我道歉。这些请求正在调用同一个 API。
  • 我理解你的代码。在你调用它两次的意义上加倍。
  • 哦。我知道了。我认为双重 API 设置具有误导性。无论如何,也许手动设置它是可行的。
  • 最后一个想法:在(2nd)API调用的处理程序中是否有任何可能的http错误报告?如果是这样,从 header-writes 乱写错误代码可能会导致 headers(在这种情况下为 Origin)永远不会被发送。
  • 显然,我的问题是由于我的自定义标头未包含在允许的标头中。 Ferrybig here 指出并解决了这个问题。不过,感谢您的努力。
猜你喜欢
  • 2020-04-03
  • 1970-01-01
  • 2019-11-10
  • 2018-08-07
  • 1970-01-01
  • 2021-03-25
  • 2022-01-23
  • 1970-01-01
  • 2016-06-04
相关资源
最近更新 更多