views:

6377

answers:

3

I'm developing a page that pulls images from Flickr and Panoramio via jQuery's AJAX support.

The Flickr side is working fine, but when I try to $.get(url, callback) from Panoramio, I see an error in Chrome's console:

XMLHttpRequest cannot load http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=processImages&minx=-30&miny=0&maxx=0&maxy=150. Origin null is not allowed by Access-Control-Allow-Origin.

If I query that URL from a browser directly it works fine. What is going on, and can I get around this? Am I composing my query incorrectly, or is this something that Panoramio does to hinder what I'm trying to do?

Google didn't turn up any useful matches on the error message.

EDIT

Here's some sample code that shows the problem:

$().ready(function(){ 
    var url = 'http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=processImages&minx=-30&miny=0&maxx=0&maxy=150';
    $.get(url, function(jsonp) {
        var processImages = function(data) {
            alert('ok');
        }
        eval(jsonp);
    });
});

You can run the example online.

EDIT 2

Thanks to Darin for his help with this. THE ABOVE CODE IS WRONG. Use this instead:

$().ready(function(){ 
    var url = 'http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&minx=-30&miny=0&maxx=0&maxy=150&callback=?';
    $.get(url, function(data) {
        // can use 'data' in here...
    });
});
+2  A: 

Works for me on Google Chrome v5.0.375.127 (I get the alert):

$.get('http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=?&minx=-30&miny=0&maxx=0&maxy=150',
function(json) {
    alert(json.photos[1].photoUrl);
});

Also I would recommend you using the $.getJSON() method instead as the previous doesn't work on IE8 (at least on my machine):

$.getJSON('http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=?&minx=-30&miny=0&maxx=0&maxy=150', 
function(json) {
    alert(json.photos[1].photoUrl);
});

You may try it online from here.


UPDATE:

Now that you have shown your code I can see the problem with it. You are having both an anonymous function and inline function but both will be called processImages. That's how jQuery's JSONP support works. Notice how I am defining the callback=? so that you can use an anonymous function. You may read more about it in the documentation.

Another remark is that you shouldn't call eval. The parameter passed to your anonymous function will already be parsed into JSON by jQuery.

Darin Dimitrov
Hmm ok let me try again. I'm on a different version of Chrome btw "6.0.472.51 beta".
Drew Noakes
Your code worked for me to. I updated my question with some code that draws the problem out though.
Drew Noakes
Drew Noakes
@Drew, please see my update about the `eval` statement.
Darin Dimitrov
@Darin, thanks for the update. I see your point, and I've played with a few combinations of this, but I'm yet to find a way to access the returned object. Could you update your jsFiddle example to show accessing the data? If you set the callback to `?` then the returned JSON is surrounded with parenthesis. You don't define a parameter for your callback function, and the value of `this` doesn't seem to have a response object (at least, the `.data` value is `null`).
Drew Noakes
@Drew, example updated: http://jsfiddle.net/ZfvKm/2/ as well as my post.
Darin Dimitrov
@Darin, fantastic. Many thanks. Working well now. For anyone else reading this, the inclusion of `callback=?` tells jQuery to generate a random function name internally, resulting in a call to the anonymous function you pass to `.getJSON`. Appreciated.
Drew Noakes
A: 

It's the same origin policy, you have to use a JSON-P interface or a proxy running on the same host.

David Dorward
@David, `panoramio` already sends JSONP.
Darin Dimitrov
+6  A: 

For the record, as far as I can tell, you had two problems:

  1. You weren't passing a "jsonp" type specifier to your $.get, so it was using an ordinary XMLHttpRequest. However, your browser supported CORS (Cross-Origin Resource Sharing) to allow cross-domain XMLHttpRequest if the server OKed it. That's where the Access-Control-Allow-Origin header came in.

  2. I believe you mentioned you were running it from a file:// URL. There are two ways for CORS headers to signal that a cross-domain XHR is OK. One is to send Access-Control-Allow-Origin: * (which, if you were reaching Flickr via $.get, they must have been doing) while the other was to echo back the contents of the Origin header. However, file:// URLs produce a null Origin which can't be authorized via echo-back.

The first was solved in a roundabout way by Darin's suggestion to use $.getJSON. It does a little magic to change the request type from its default of "json" to "jsonp" if it sees the substring callback=? in the URL.

That solved the second by no longer trying to perform a CORS request from a file:// URL.

ssokolow