跨域请求被阻止:多个 API;需要聚合数据

Cross-Origin Request Blocked: Multiple API; need to aggregate data

Objective: 从至少 3 API 获取几天的 precipIntensity。 主要问题:Cross-Origin Request Blocked,导致数据未定义。什么是跨域请求?我该如何解决这个干扰 If() 语句并将收集到的 JSON 数据收集到聚合中以获得均值沉淀的问题? 更新的解决方案:

    //Get the back dated times and current in UNIX, 
   //later make a lookup that gives datediff from current date and user's date and adjust index i condition to equal exact days.
            var totalPrecipSinceDate;
            var threeDayAPITimes = [];

        for (var i = 0; i <= 2; i++) //place user userData-1 where i <= input
    {
        var myDate = new Date(); //
        var epoch = myDate.getTime(); 
        var unixEpoch = Math.round(epoch/1000)
        threeDayAPITimes[i] = Math.round(unixEpoch - (86400 * i));

    }
    //Plan to convert UNIX dates to display

    //List of locations: LATITUDE,LONGITUDE
    var locations = ["46.3494,-85.5083"]

    //setup a server-side proxy which would hide the API key from the client side
    var currentAPIKey ="privateKey"; //gets an APIkey from user input.



var listAPIs = "";

$.each(threeDayAPITimes, function(i, time) {
    var darkForecastAPI= "https://api.forecast.io/forecast/" + currentAPIKey + "/" + locations + "," + time +"?callback=?"; 
     $.getJSON(darkForecastAPI, {
        tags: "WxAPI[" + i + "]",  //Is this tag the name of each JSON page? I tried to index it incase this is how to refer to the JSON formatted code from the APIs.
        tagmode: "any",
        format: "json"
    }, function(result) {
        // Process the result object    
        var eachPrecipSum = 0;
    if(result.currently.precipIntensity >=0 && result.currently.precipType == "rain")
        {
            $.each(result, function() {
              eachPrecipSum += (this.currently.precipIntensity);
              totalPrecipSinceDate += eachPrecipSum ;  ///Write mean precip
                        alert(eachPrecipSum );
        });

    }   
});
});

您正在尝试调用由域 api.forecast.io 提供的 URL,该域不同于您的 javascript 代码的来源域,因此它是一个跨域请求。

其他域不支持CORS。这可以通过其他域添加 ACAO header 来解决。

CORS

无需在客户端 JavaScript 调用 Ajax,您可以在服务器端代码中执行此操作,而不必处理 CORS。 Google: CORS 代理 {您的服务器端语言}

A Cross-Origin 请求是指您向另一个域发出请求。为了保护用户,默认情况下不允许这样做。浏览器使用同源策略。这意味着您只能在同一域上发出请求。

无法解决跨源请求问题。 forecast.Io 的所有者必须使用 HTTP header 授权您的域。我猜他们不会那样做。基本上,CORS 让源代码控制谁可以使用 API,而不是消费者。

您最好的选择可能是解决该限制。您将需要使用 JSONP。他们支持这一点,但在 documentation 中注意到这一非常明智的警告: Return API 响应为 JSONP。使用它时请小心,因为将 API 密钥暴露给 public 是一种安全隐患,如果被滥用,将导致您的 API 密钥被撤销。但是,如果开发个人或 internal-use 应用程序,这是一种方便的方法。

要启用 JSONP,只需输入 ?callback=?作为您的 URL 的查询字符串。这将使 jQuery 设置 JSONP。在您的示例中,您可以在构建 URL 的任何地方执行此操作,因此此处:

var darkForecastAPI= "https://api.forecast.io/forecast/" + currentAPIKey + "/" + locations + "," + time +"?callback=?";

但是,正如他们所说,您的 API 密钥已暴露,因此请小心。如果可能,请在您的服务器上创建一个 server-side 网络服务,作为您的 JavaScript 和他们的 API 之间的代理。不确定这是否可行,但在他们的网站上,他们提供了一个用 PHP 编写的,你可以很容易地用任何语言编写一个。

让我也给你一些关于 JSONP 的背景,因为这可能是你第一次听说它。有风险。与returnsobjects中的JSON不同,JSONP其实调用了一个JS函数,直接执行代码。这意味着如果存在恶意站点,它可能会造成损害。我不会太担心 forecast.Io,但如果它是 someshadyrussianmp3site 我会小心!它的工作方式是在您的页面中注入一个 <script src="http://forecast.io/blah/blah/blah/?callback=jquery_12345" ></script> 标记。脚本标签没有同源限制。该文件基本上将 JSON object 包装到对 jquery_12345 的调用中,jQuery 为您抽象,因此它像正常一样工作。除了安全之外,另一个缺点是没有好的方法来检测故障。 JQuery 将通过超时来帮助 "assume" 失败,但您不会收到 500 错误或任何与 true JSON.[=13= 相同的错误]

这里不需要任何花哨的东西,因为请求可以在不到 10 行普通的旧代码中完成 Javascript。点击下方"Run Code Snippet"进行测试。

另一种选择是使用 Yahoo,它每天 return 1000 个预测而无需 API 键。此处有更多详细信息:Yahoo Weather

    <html>
    <head>
         <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/json2/20140204/json2.min.js"></script>
    </head>
    <body>
    
    <xmp id="stdout"></xmp>
    <script type="text/javascript">
    
     function callback( data ) {
      // do something with the forecast data 
      document.getElementById('stdout').innerHTML = JSON.stringify( data, null, '\t' ); 
     }
    
     var head = document.head || document.getElementsByTagName('head')[0] || document.documentElement;
     var script = document.createElement('script');
     script.type = 'text/javascript';
     script.src = 'https://api.forecast.io/forecast/c52dea83654f200f77cf97db47fdd03e/46.3494,-85.5083?callback=callback'
     head.appendChild(script);
    
    </script>
    </body>
    </html>