0

I am testing out this script which retrieves the weather data from the URL. But for some reason I am not getting the response back. I have enabled cross-site. Can someone point out the problem?

<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js">
</script>
<script>
$(document).ready(function(){
  $("button").click(function(){
  $.ajax({
      type:"GET",
      url:"http://api.openweathermap.org/data/2.5/weather?q=London", 
      headers: { "Accept": "application/json; odata=verbose" },
      crossDomain:true, 
      success:function(result){
           $("#div1").html(result);
      }});
    });
});
</script>
</head>
<body>

<div id="div1"><h2>Let jQuery AJAX Change This Text</h2></div>
<button>Get External Content</button>

</body>
</html>
Fox
  • 9,384
  • 13
  • 42
  • 63

5 Answers5

2

This is the error in chrome dev console :

XMLHttpRequest cannot load http://api.openweathermap.org/data/2.5/weather?q=London. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost.com' is therefore not allowed access.

How can you say that you have enabled cross-site ? You are querying the openweathermap server, and you are not from openweathermap... Cross site enabling is not just enough setting headers in ajax. The server needs to enable its servlets (or so) to respond for ajax requests of any domain. Only then our ajax calls will be getting information from them.

Siva Tumma
  • 1,695
  • 12
  • 23
  • "Cross site enabling is not just enough setting headers in ajax" - actually what the server does is _exactly_ send HTTP headers that allow it :) – Benjamin Gruenbaum Dec 27 '13 at 18:24
2

Soultion1

if you have php on your server create a file called weather.php width this code on the same domain as your page.

<?php
echo file_get_contents('http://api.openweathermap.org/data/2.5/weather?q='.$_GET['q']);
?>

and call it with your function

url:"weather.php?q=London",

Note: slow but real ajax

Soultion2

if openweathermap.org has support for callbacks you can use jsonp

Note: fills the page with <srcip></script> tags.

Soultion3

use a nodejs proxy

Note: fast & real ajax

Soultion4

using a yql query.

Note: fastest & real ajax

if you need more details just ask

EDIT

Solution5

A Fast way to passtrough the content with php

<?php
function w($ch,$chunk){ 
 echo $chunk;
 ob_flush();
 flush();
 return strlen($chunk);
};
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
$ch=curl_init();
curl_setopt($ch,CURLOPT_URL,$_GET['url']);
curl_setopt($ch,CURLOPT_BINARYTRANSFER,1);
curl_setopt($ch,CURLOPT_WRITEFUNCTION,w);
curl_exec($ch);
curl_close($ch);
?>

Note: faster than file_get_contents & real ajax

by removing the

header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');

part it's even faster.

EDIT3

proxy's are always a bad idea vs direct as you read the data always 2 times.

direct action

ask->read->display

proxy action

ask->(php/node ask)->(php/node read)->(php/node display)->read->display

but in your case there is no other way to get the data directly.


i tagged the yql as fastest based on average hosts.

most of the data from important sites like openweathermap is probably already cached on the yahoo servers and the their bandwith is very high worldwide (and crossorigin is allowed).

so if you have a slow host that needs to read the data from openweathermap with php or nodejs & then output having a limited bandwidth it's 99% slower than on yahoo's server.


nodejs is faster than php because if you create o good dedicated proxy script you store your data directly inside the system memory. Caching data inside the memory is faster than anything else i know.probaly it's even faster then reading a static file.

the point is how fast your host outputs the request.

cocco
  • 16,442
  • 7
  • 62
  • 77
  • 1
    I don't think that a php proxy is automatically much slower than a NodeJS one. Your cases are good, but why is one better than the other? Which would you do? Why? – Benjamin Gruenbaum Dec 27 '13 at 18:23
  • php is much slower... based on tests i made some time ago if you are not on a good host as you need to read the content 2 times. nodejs handles this type of communication faster. yql query is on the yahoo servers and some data is already cached. jquery is bah.. – cocco Dec 27 '13 at 18:26
  • 1
    a same cpu server handles the content of a nodejs script much faster than php. i wrote also a nice curl example witch is relatively fast wich reads the content with a write function and flusches the data.. but for a short answer like that it's prolly not necessary. – cocco Dec 27 '13 at 18:30
  • 2
    Look, I really don't want to get into an argument about your benchmark is and that you should compare Node's `http` library client to something like [Atrax](https://github.com/rdlowrey/Artax) and certainly not to `file_get_contents`... the fact _a_ slow blocking HTTP client exists in PHP does in no way mean there are no fast ones. Please don't spread FUD, it's perfectly possible to write this sort of 'proxying' in PHP, Python, JavaScript with node or pretty much any other language... Please consider editing your answer to elaborate more on the cases and their advantages/disadvantages. – Benjamin Gruenbaum Dec 27 '13 at 18:33
  • Also - The issue here really isn't the proxy speed - it's why a proxy is a good/bad idea. What advantages does each approach have and so on. – Benjamin Gruenbaum Dec 27 '13 at 18:43
  • the point is your host. if you retrieve cached data from a yahoo server it's prolly faster all over the world than from a static server located somewhere.then if you want to use php or node.. that depends on your possibilities.i hade better responses with nodejs. – cocco Dec 27 '13 at 18:43
  • and i don't like jsonp because it has memoryleaks (on many calls).as you continuosly add and remove lements inside a page. – cocco Dec 27 '13 at 18:51
1

You need to set the dataType in the ajax call to "jsonp". Check out this jsFiddle. I found the answer (essentially) from this SO post.

$("button").click(function(){
   $.ajax({
       type:"GET",
       url:"http://api.openweathermap.org/data/2.5/weather?q=London",
       dataType : "jsonp",
       success:function(result){
           console.log(result);
            $("#div1").html(result['name']);
       },
       error: function(xhr, status, error) {
           console.log(status);
       }
     });
});

To give a little more background on why this is needed:

This is basically a way to get around browsers and cross-site protection (per my understanding--it looks like suspicious behavior to browsers). Nowadays, server owners can allow cross-site origin requests (CORS), but if the server owner (openweathermap in this case) does not, you can still request data via jsonp (see this wikipedia entry for more details: en.wikipedia.org/wiki/JSONP)

Community
  • 1
  • 1
user
  • 4,651
  • 5
  • 32
  • 60
  • This is basically a way to get around browsers and cross-site protection (per my understanding--it looks like suspicious behavior to browsers). Nowadays, server owners can allow cross-site origin requests (CORS), but if the server owner (openweathermap in this case) does not, you can still request data via jsonp (see this wikipedia entry for more details: http://en.wikipedia.org/wiki/JSONP) – user Dec 27 '13 at 18:23
0

try this you forgot to put JSONP which is used for cross domain requests:

<!DOCTYPE html>
<html>
<head>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js">
    </script>
    <script>
        $(document).ready(function() {
            $("button").click(function() {
                $.ajax({
                    type: "GET",
                    dataType: "jsonp",
                    url: "http://api.openweathermap.org/data/2.5/weather?q=London",
                    crossDomain: true,
                    success: function(result) {
                        console.log(result);
                        $("#div1").html(result.clouds.all);
                    }
                });
            });
        });
    </script>
</head>
<body>
    <div id="div1"><h2>Let jQuery AJAX Change This Text</h2></div>
    <button>Get External Content</button>
</body>
</html>
Susheel Singh
  • 3,824
  • 5
  • 31
  • 66
  • What do you mean "JSONP" is used for cross domain requests? Are there any problems with it? Why would I want it? Why would I avoid it? – Benjamin Gruenbaum Dec 27 '13 at 18:23
  • http://stackoverflow.com/questions/2067472/what-is-jsonp-all-about check this link for clear explaination and in short if we need cross domain request we use jsonp – Susheel Singh Dec 27 '13 at 18:24
  • __I__ know what JSONP is :) I was making suggestions on how I think you can/should update your answer - code only answers are discouraged in StackOverflow - try explaining the rationale. – Benjamin Gruenbaum Dec 27 '13 at 18:27
  • user needs solutions sometimes rather than its details. you are welcome to explain jsonp in simpler terms. – Susheel Singh Dec 27 '13 at 18:29
0

Your forgot dataType:"jsonp" attribute in ajax request.

  • I don't think he forgot it, why would he need to type it? What does it do? – Benjamin Gruenbaum Dec 27 '13 at 18:22
  • https://en.wikipedia.org/wiki/Same_origin_policy - jsonp allows a page to receive JSON data from a different domain by adding a – user3140081 Dec 27 '13 at 18:35
  • A link to the wikipedia article about the same origin policy is in no way a reasonable explanation to OP's issue and why this solves it. – Benjamin Gruenbaum Dec 27 '13 at 18:36
  • I don't get you.. If you have to receive data from different domain, either you would go for jsonp or cors, given that cors is new in mobile devices, probably he meant jsonp... may be I had the question wrong :) – user3140081 Dec 27 '13 at 18:48
  • I get that, I was merely suggesting you elaborate more in your answer. I'm aware of CORS and JSONP and the downfalls and pros/cons of each - but OP isn't. When you answer a question it's best if you explain it rather than just tell him "use X" – Benjamin Gruenbaum Dec 27 '13 at 18:54