5

I have no trouble making jsonp requests, however I'm unsure about setting up a web service to deliver responses in jsonp.

First, does a server need to be configured in a certain way to allow jsonp requests, or does the page just have to have the response properly formatted?

In my testing I have the following jsonp response from geonames.org (I've placed it a blank page on server/domain 1 with nothing else):

<?php echo $_GET['callback'];?>({"postalcodes":[{"adminName2":"Westchester","adminCode2":"119","postalcode":"10504","adminCode1":"NY","countryCode":"US","lng":-73.700942,"placeName":"Armonk","lat":41.136002,"adminName1":"New York"}]});

On server/domain 2 I'm making the following request:

$.ajax({
    // works when I make the call to geonames.org instead of domain1
    //url: 'http://www.geonames.org/postalCodeLookupJSON?postalcode=10504&country=US&callback=?',,
    url: 'http://www.domain1.com/test/jsonp.php?callback=?',
    success: function(data) {
        $('#test').html(data);
    },
});

The call works when I place the files on the same server (either domain 1 or 2) and turn it into a regular json request. What am I doing wrong?

Just to clarify: My question pertains to the page RECEIVING the request. I know the request works when I make it to geonames.org, flickr, etc... apis. However, I'm trying to set up a page to send a response. In my example I just have a blank page with hard coded jsonp. I'm not sure if I have to have some other headers on the page or have something enabled on my server.

Choy
  • 2,087
  • 10
  • 37
  • 48
  • is the caller and server exists on same domain ??? – kobe Dec 07 '10 at 04:36
  • @gov, no they do not. My example is using three different servers (and domains). Domain 1 requesting data from geonames.org works. Taking the response from geonames.org and placing it on a blank page on Domain 2 and making the same request from Domain 1 to Domain 2 doesn't work. Same for reversing it and making the request from Domain 2 to Domain 1. – Choy Dec 07 '10 at 04:46
  • Had to add an access control header to make it work: header('Access-Control-Allow-Origin: *'); (in PHP) – Choy Dec 07 '10 at 16:14

2 Answers2

12

The response is wrong.

If you have the following url: http://www.mydomain.com/test/jsonp.php&callback=? jQuery will replace the question mark at the end of the url with a unique string. On the serverside you have to take this string($_GET['callback']) and use it as function-name in your response:

PHP-example:

<?php
 $object=array('postalcodes'
                  =>array(
                            array(
                                    "adminName2"  =>  "Westchester",
                                    "adminCode2"  =>  "119",
                                    "postalcode"  =>  "10504",
                                    "adminCode1"  =>  "NY",
                                    "countryCode" =>  "US",
                                    "lng"         =>  -73.700942,
                                    "placeName"   =>  "Armonk",
                                    "lat"         =>  41.136002,
                                    "adminName1"  =>  "New York"
                                   )));

   echo $_GET['callback'].'('.json_encode($object).')';
?>

What happens with the response when receiving it? jQuery knows the unique string(assuming fx123456).
jQuery will create a <script>-element with the src: http://www.mydomain.com/test/jsonp.php&callback=fx123456 . jQuery will call a on the fly created function named fx123456() . This function will return the JSON(as a object) which will be taken as data-argument of the success-function of $.ajax().

So if you don't use the callback-parameter provided by jQuery as functions-name inside the response, jQuery doesn't know the name of function to call(I better say jQuery will call a function that doesn't exist).

Dr.Molle
  • 116,463
  • 16
  • 195
  • 201
  • thank you, that clarifies things a lot! I tried your sample response, in addition to just using $_GET['callback'] and writing the jsonp out as plain text, but both still respond with a blank page when I try to access it using the $.ajax call. It outputs correctly when accessing the page directly from the browser and changes the callback to whatever I set it to in the browser url as well. Switching the url of the server to geoname's api works fine, so the call on the client side is ok. Could there possibly by some hosting/server setting I need to change? – Choy Dec 07 '10 at 05:25
  • You'll have to set the dataType-option of `$.ajax()` to `jsonp`. Or use $.getJSON() instead. – Dr.Molle Dec 07 '10 at 05:51
  • 1
    Got it! I needed to add a an access control header: header('Access-Control-Allow-Origin: *'); Thanks for your help. – Choy Dec 07 '10 at 16:13
0

I've always used $.getJSON() in place $.ajax for cross-browser requests so I don't know the specifics on calling json using $.ajax as you have here, but have you tried setting the dataType to jsonp?

Also, have you tried ?callback=? instead of &callback=?

$.ajax({
    url: 'http://www.mydomain.com/test/jsonp.php?callback=?',
    dataType: 'jsonp',
    success: function(data) {
        $('#test').html(data);
    },
});

Lastly, when I run your test json into jsonlint.com it is not returning valid. It says syntax error, unexpected TINVALID at line 1 Parsing failed

jyoseph
  • 5,435
  • 9
  • 45
  • 64
  • I have tried using $.get instead and setting the data type to jsonp with no luck. It's returning invalid because the json is wrapped in ?(); for the jsonp callback. But it works (it was taken from the geonames.org api). – Choy Dec 07 '10 at 04:51
  • In case anyone is still looking at this for guidance, don't add the callback to the query string, jquery will do that for you if you specify jsonp. – ldg Jun 07 '13 at 15:24