跨域请求被阻止:多个 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 来解决。
无需在客户端 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>
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 来解决。
无需在客户端 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>