Search code examples
javascriptjqueryajaxjsonweather-api

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


Objective: Get precipIntensity for several days from at least 3 API. Main issue: Cross-Origin Request Blocked, causing data to be undefined. What is a cross-origin request and how might I resolve this issue that interferes with the If() statement and gathering the collected JSON data into aggregates for mean precip? Updated Solution:

    //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(); //http://stackoverflow.com/questions/7693170/javascript-convert-from-epoch-string-to-date-object
        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 );
        });

    }   
});
});

enter image description here

enter image description here


Solution

  • A Cross-Origin Request is when you're making a request to another domain. To protect the user, that's not allowed by default. Browsers work on the same origin policy. This means that you can only make requests on the same domain.

    You can't solve the Cross Origin Request problem. The owner of forecast.Io would have to authorize your domain with an HTTP header. I'm guessing they're not going to do that. Basically CORS gives the source control over who can use the API, not the consumer.

    What you're best bet is likely to be is to work around the limitation. You will need to use JSONP. They support this but note this very wise caution in their documentation: Return the API response as JSONP. Please use caution when using this, since exposing your API key to the public is a security hazard and, if abused, will result in the revokation of your API key. However, if developing a personal- or internal-use app, this is a convenient method of doing so.

    To enable JSONP, simply put ?callback=? As the query string of your URL. This will make jQuery setup JSONP. In your example you'd do this anywhere you build the URL, so here:

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

    However, as they mention, your API key is exposed so be careful. If possible, make a server-side web service on your server that acts as a proxy between your JavaScript and their API. Not sure if that is possible but on their site they provide one written in PHP and you could write one in any language fairly easily.

    Let me also give you a little background on JSONP since this is probably the first time you've heard of it. There are risks. Unlike JSON which returns objects, JSONP actually calls a JS function and executes code directly. That means if there is a malicious site, it could cause damage. I wouldn't worry too much about forecast.Io, but if it's someshadyrussianmp3site I'd be careful! The way it works is it injects a <script src="http://forecast.io/blah/blah/blah/?callback=jquery_12345" ></script> tag in your page. Script tags don't have the same origin restriction. That file basically wraps a JSON object into a call to jquery_12345 which jQuery abstracts for you so it works like normal. The other downside, other than security, is there is no good way to detect failure. JQuery will help by having a timeout that it can use to "assume" a failure, but you won't get a 500 error or anything like you would with true JSON.