views:

1210

answers:

5

I have a two domains, example1.com and example2.com

From example1.com, I would like call a JSON API I have on example2.com. Knowing that this is not allowed, it occurred to me - this is exactly why JSON**P** was created.

Question is, how do I modify my JSON API to make it JSONP capable?

Basically, how do I create the callback api?

UPDATE

My server side language is PHP

A: 

example here http://www.insideria.com/2009/03/what-in-the-heck-is-jsonp-and.html basically

<script src=".../example2...?output=json;callback=loadit"></script>
<script>
alert( "I got this from example2 " + loadit);
</script>
asdf
+7  A: 

You need a server-side language, the callback parameter is simply a GET parameter, you read the param, and you wrap the JSON response into a function call and you print it like this callback(jsonResponse);.

I leave you a really minimalist example using Python since you don't mention any server-side language:

import os
import cgi

form = cgi.FieldStorage()
callback = form.getvalue('callback','')

address = cgi.escape(os.environ["REMOTE_ADDR"])

json = '{"ip": "'+address+'", "address":"'+address+'"}'

#Allow cross domain XHR
print 'Access-Control-Allow-Origin: *'
print 'Access-Control-Allow-Methods: GET'

if callback != '':
  print 'Content-Type: application/javascript'
  result = callback+'('+json+');'
else:
  print 'Content-Type: application/json'
  result = json

print ''
print result

That is the code of a small JSONP service used to retrieve the client IP address made by Zach and it is hosted on the Google App Engine.

CMS
+6  A: 

It is simple. Simply accept a parameter called callback in the GET.

Then warp the callback Javascript function around your data.

Example in PHP:

<?php

header('Content-Type: text/javascript; charset=utf8');
header('Access-Control-Allow-Origin: http://www.example.com/');
header('Access-Control-Max-Age: 3628800');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE');

$callback = $_GET['callback'];

$data = '{}'; // json string

echo $callback.'('.$data.');';

?>

It's simply to return a javascript file which calls the callback function with the JSON object as the first parameter

thephpdeveloper
Wow, is it really just that simply?
Teddi
Do I need to add: echo 'Access-Control-Allow-Origin: *'echo 'Access-Control-Allow-Methods: GET' ???
Teddi
@Teddi: Those headers are to support the upcoming XMLHttpRequest 2 specification (http://www.w3.org/TR/access-control/) and BTW they already work on Firefox 3.5 (https://developer.mozilla.org/en/HTTP_access_control)
CMS
@Mauris, would you mind updating your code to include the new XMLHttpRequest v2 spec headers. thanks
Teddi
@Teddi - it's not that important because it's upcoming. It'll work with the script tag hack. Anyway I've added the headers in.
thephpdeveloper
Please be sure to filter your callback parameter so only alpha, numeric, dot, and square brackets are valid characters. Otherwise you're stepping into a world of hurt.
Kent Brewster
A: 

Mauris already gave you a working example. I would only add that you should check if a callback param is present and non-empty, and if not, return the json data as is without the parentheses. So basically your api will be JSON with provision of being JSON-P when callback is given.

To consume the JSON-P webservice, unless you use a framework like YUI or jQuery, you can simply create a script node dynamically and set its src attribute to point to the webservice. Remember to remove the node from the dom before repeating it again, since this dynamic script node is single use only.

Joy Dutta
+1  A: 

Easy with jQuery, that is the client side:

  $.ajax({
     dataType: 'jsonp',
     data: "somedata="+somevalue,
     //this is very important since it's the callback we will and that allow cross domain
     jsonp: 'jsonp_callback',
     url: 'http://example2.com',
     //function we trigger on success
     success: ParseJson
         //error handling not working with jsonP
      //error: handleError
     });

function ParseJson(data)
{
for (var key in data) {
  if (data.hasOwnProperty(key)) {
    alert(key + " -> " + data[key]);
  }
}
}

And be sure that you get proper json from the server side;
and don't forget to return the jsonp_callback param, otherwise it won't work!!!!!
and that's it really.

Tom