【问题标题】:Axios request to yahoo weather API failingAxios 对 yahoo 天气 API 的请求失败
【发布时间】:2018-02-01 14:57:16
【问题描述】:

我正在开发一个 vuejs 组件,该组件使用 axios 向 Yahoo 天气 API 发出 ajax GET 请求。我收到 CORS 错误,因为预检检查未通过访问控制检查。

但是,我可以毫无问题地使用 jqueries ajax 方法向同一个端点发出请求,并且从服务返回预期的数据。有谁知道为什么会这样?

这是我的 vue 组件中的代码:

<template>
    <div class="tile" id="time-weather">
        <div class="date" v-text='this.date'></div>
        <div class="time" v-text='this.time'></div>
        <div class="temperature" v-text="this.temp"></div>
    </div>
</template>

<script>
    import moment from 'moment';

    export default {
        created() {
            this.refreshTime();
            setInterval(this.refreshTime, 1000);

            this.fetchWeather();
        },
        data() {
            return {
                date: '',
                time: '',
                temp: ''
            }
        },
        methods: {
            refreshTime() {
                this.date = moment().format('ddd DD/MM');
                this.time = moment().format('HH:mm:ss');
            },
            fetchWeather() {
                const endpoint = "https://query.yahooapis.com/v1/public/yql?q=select item.condition from weather.forecast where woeid in (select woeid from geo.places(1) where text='Sunderland') and u='c'&format=json";
                const yapi = axios.create({
                    url: endpoint,
                    method: 'get',
                    withCredentials: false
                });

                const response = yapi.request();
                console.log(response);
            } 

        }
    }
</script>

我在控制台中收到的确切错误消息是:

XMLHttpRequest 无法加载 https://query.yahooapis.com/v1/public/yql?q=select%20item.condition%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text=%27Sunderland%27)%20and%20u=%27c%27&format=json。 对预检请求的响应未通过访问控制检查:否 请求中存在“Access-Control-Allow-Origin”标头 资源。因此不允许使用原点“http://dashboard.dev” 访问。

正如我所提到的,如果我使用 jQuery.ajax(); 向同一个端点发出请求,则请求将毫无问题地发送。

我可能缺少一些明显的东西,但我似乎无法解决这个问题。

任何帮助将不胜感激。

干杯!

【问题讨论】:

  • 你确定吗?给定端点返回 404。刚刚用 cURL 检查了它。
  • @jimmyweb 编辑了指向 https 的链接,我的错。仍然得到相同的结果。
  • 查看刚刚添加的答案。您可以进入浏览器 devtools 中的 Network 窗格并重新加载文档,然后在那里检查浏览器发送的 preflight OPTIONS 请求。您应该检查请求标头 - 特别是浏览器发送的 Access-Control-Request-Headers 请求标头。这将包含 axios 请求尝试添加到请求中的任何自定义请求标头的名称(这会导致预检失败)。也许使用stackoverflow.com/posts/45849535/edit 来编辑/更新问题并粘贴到这些响应标题中。

标签: jquery ajax cors vuejs2 axios


【解决方案1】:

我收到了回复,但我需要使用 https,而不是 http - 对于 axios 和 JQuery 都是如此。

运行下面的 sn-p 或此 CodePen Demo 以查看响应:

axios.get(
    "https://query.yahooapis.com/v1/public/yql?q=select item.condition from weather.forecast where woeid in (select woeid from geo.places(1) where text='Sunderland') and u='c'&format=json"
  )
  .then(function(result) {
    console.log(result);
  });
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.12.0/axios.min.js"&gt;&lt;/script&gt;

【讨论】:

  • 感谢丹的回复。如果我自己运行代码 sn-p 就可以了,我之前也尝试过。每当我尝试在 vuejs 组件中使用它作为 Laravel 应用程序的一部分时,它都不会。不完全确定为什么!
  • 有趣。 This link 是一个有趣的例子,有人在带有 vuejs 的 yahoo 天气 api 上使用 axios。此人还使用 get 和 then 方法进行 ajax 响应。希望这可能会有所帮助:) –
【解决方案2】:

仅从问题中的当前详细信息来看,无法确定您的浏览器为什么会生成 CORS preflight OPTIONS request,但可以确定的一件事是它失败的原因是因为 https://query.yahooapis.com/v1/public/yql 端点没有t 在OPTIONS 响应中发送Access-Control-Allow-Origin 响应标头。

您可以通过这样做来确认使用curl

curl -X OPTIONS -i \
   -H 'http://dashboard.dev/' \
  'http://query.yahooapis.com/v1/public/yql?q=select%20item.condition%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text=%27Sunderland%27)%20and%20u=%27c%27&format=json'

HTTP/1.1 200 OK
Allow: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS
Content-Length: 0
Date: Wed, 23 Aug 2017 22:12:40 GMT
Age: 0
Connection: keep-alive
Via: http/1.1 a44.ue.sg3.yahoo.net (ApacheTrafficServer [c sSf ])
Server: ATS

我正在开发一个 vuejs 组件,该组件使用 axios 向 Yahoo 天气 API 发出 ajax GET 请求。我在预检检查中收到 CORS 错误……如果我使用 jQuery.ajax() 向同一端点发出请求,则发送请求没有问题。

这表明jQuery.ajax() 没有以触发预检的方式发出请求,但 axios 请求是。几乎可以肯定,axios 请求添加了一个或多个自定义请求标头——我猜可能是X-Requested-With 标头*——jQuery.ajax() 不是。

更新:在这种情况下,添加的标头是X-CSRF-TOKEN

要确定到底发生了什么,请检查浏览器发送的 OPTIONS 请求——特别是 OPTIONS 请求中的 Access-Control-Request-Headers 请求标头。这将包含 axios 请求尝试添加到请求中的任何自定义请求标头的名称。

您可以查看OPTIONS 请求的标头和其他详细信息,方法是进入浏览器开发工具中的“网络”窗格并重新加载,然后在那里检查OPTIONS 请求。


无论如何,有一种方法可以让您向该端点发出请求,使其按预期工作。您可以通过 CORS 代理发出您的请求,方法是更改​​您的前端代码以具有此:

const proxyurl = "https://cors-anywhere.herokuapp.com/";
const endpoint = "https://query.yahooapis.com/v1/public/yql?q=select item.condition from weather.forecast where woeid in (select woeid from geo.places(1) where text='Sunderland') and u='c'&format=json";
const yapi = axios.create({
    url: proxyurl + endpoint,
    method: 'get',
    withCredentials: false
});

这将通过https://cors-anywhere.herokuapp.com 发送请求——浏览器的预检OPTIONS 请求和您的GET 请求。那里的后端将请求转发到https://query.yahooapis.com/v1/public/yql 端点并接收响应。

然后,后端将Access-Control-Allow-Origin 标头添加到响应中——在OPTIONS 的情况下,还添加Access-Control-Allow-HeadersAccess-Control-Allow-Methods 响应标头——然后将其传递回您的请求前端代码。

然后浏览器将允许您的前端代码访问响应,因为带有Access-Control-Allow-Origin 响应标头的响应是浏览器看到的。

您还可以使用 https://github.com/Rob--W/cors-anywhere/ 轻松设置自己的 CORS 代理

【讨论】:

  • 感谢您的回答。它失败的原因是在 Laravel bootstrap.js 文件中,axios 在请求中添加了 X-CSRF-TOKEN 标头。一旦我删除它,请求就被发送并且数据按预期返回。再次感谢您的帮助!
  • OK 是的,这是有道理的,因为在请求中添加 X-CSRF-TOKEN 标头将触发浏览器执行 OPTIONS 预检。干杯,很高兴你明白了!
猜你喜欢
  • 2019-05-28
  • 2020-11-26
  • 1970-01-01
  • 2017-03-25
  • 2017-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-09
相关资源
最近更新 更多