Axios请求雅虎天气API失败

时间:2017-08-23 21:26:47

标签: jquery ajax cors vuejs2 axios

我正在研究一个vuejs组件,该组件使用axios向Yahoo weather 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();向同一个端点发出请求,则发送请求时没有任何问题。

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

非常感谢任何帮助。

干杯!

2 个答案:

答案 0 :(得分:2)

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

您可以通过以下方式确认使用OPTIONS

curl
  

我正在研究一个vuejs组件,该组件使用axios向Yahoo weather API发出ajax GET请求。我收到一个CORS错误,因为预检检查......如果我使用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 向同一个端点发出请求,则发送请求时没有问题。

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

* 更新:在这种情况下,添加的标头是jQuery.ajax()

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

您可以访问浏览器的“网络”窗格,然后重新加载,然后在那里检查OPTIONS请求,以查看OPTIONS请求的标题和其他详细信息。

无论如何,无论如何,有一种方法可以让请求到该端点按预期工作。您可以通过CORS代理发出请求,通过更改前端代码来实现此目的:

OPTIONS

这将通过https://cors-anywhere.herokuapp.com发送请求 - 浏览器的预检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 }); 请求和OPTIONS请求。然后,后端将请求转发到GET端点并接收响应。

然后,后端将https://query.yahooapis.com/v1/public/yql标头添加到响应中 - 如果是Access-Control-Allow-Origin,还有OPTIONSAccess-Control-Allow-Headers响应标头 - 然后通过回到你要求的前端代码。

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

您还可以使用https://github.com/Rob--W/cors-anywhere/

轻松设置自己的CORS代理

答案 1 :(得分:1)

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

运行下面的代码段或 CodePen Demo 以查看回复:

&#13;
&#13;
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);
  });
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.12.0/axios.min.js"></script>
&#13;
&#13;
&#13;