I'm doing the JavaScript challenges at FreeCodeCamp. One of them is to create a web page that retrieves and displays weather information.
First, I tried to use several providers (e. g. OpenWeatherMap, WeatherUnderground), which use the HTTP protocol to return weather data. It didn't work because of the mixed content error.
Next, I switched to a provider, which delivers the data via HTTPS. I got rid of the mixed content problem, but got another one:
XMLHttpRequest cannot load https://api.weatherbit.io/v1.0/current?lat=55.7767723&lon=37.6090795&units=S&key=XXXXXXXX. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://s.codepen.io' is therefore not allowed access. The response had HTTP status code 403.
I tried to implement CORS according to this tutorial:
function createCORSRequest(method, url) {
var xhr = new XMLHttpRequest();
if ("withCredentials" in xhr) {
// Check if the XMLHttpRequest object has a "withCredentials" property.
// "withCredentials" only exists on XMLHTTPRequest2 objects.
xhr.open(method, url, true);
} else if (typeof XDomainRequest != "undefined") {
// Otherwise, check if XDomainRequest.
// XDomainRequest only exists in IE, and is IE's way of making CORS requests.
xhr = new XDomainRequest();
xhr.open(method, url);
} else {
// Otherwise, CORS is not supported by the browser.
xhr = null;
}
return xhr;
}
[...]
var url = "https://api.weatherbit.io/v1.0/current?lat=" + position.coords.latitude + "&lon=" + position.coords.longitude + "&units=S&key=XXXXXXXX";
var xhr = createCORSRequest('GET', url);
if (xhr) {
xhr.onload = function() {
var responseText = xhr.responseText;
console.log("Response: " + responseText);
};
xhr.onerror = function() {
console.log('There was an error!');
};
xhr.send();
}
When I call xhr.send()
I still get the error.
How can I fix it?
Note: I'm looking for a solution that will run in CodePen.
Update 1 (23.03.2017 11:35 MSK): I tried to implement sideshowbarker's answer and modified the code like this:
function getCurrent(json){
console.log("getCurrent called");
console.log(json.data.temp);
console.log(json.data.precip);
}
function updateWeather() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var url = "https://api.weatherbit.io/v1.0/current?callback=getCurrent&lat=" + position.coords.latitude + "&lon=" + position.coords.longitude + "&units=S&key=XXXXXXXXX";
console.log("url: " + url);
$.get(url, function(val){});
});
} else {
console.log("Cannot obtain location data");
};
}
updateWeather();
The result:
Update 2 (23.03.2017 13:29 MSK): This one works.
function getCurrent(json) {
console.log("getCurrent called");
console.log(JSON.stringify(json));
// TODO: Update the UI here
}
function updateWeather() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var url = "https://api.darksky.net/forecast/XXXXXXXXX/37.8267,-122.4233?callback=getCurrent";
var script = document.createElement('script');
script.src = url;
document.getElementsByTagName('head')[0].appendChild(script);
});
}
}
updateWeather();