Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can anyone explain what JSONP is, in layman terms? [duplicate]

Tags:

jquery

jsonp

I know JSONP is JSON with padding.

I understand what JSON is, and how to use it with jQuery.getJSON(). However, I do not understand the concept of the callback when introducing JSONP.

Can anyone explain to me how this works?

like image 297
Someone Avatar asked Oct 01 '10 14:10

Someone


People also ask

What is meant by JSONP?

JSONP stands for JSON with Padding. Requesting a file from another domain can cause problems, due to cross-domain policy. Requesting an external script from another domain does not have this problem. JSONP uses this advantage, and request files using the script tag instead of the XMLHttpRequest object.

What is the difference between JSON and JSONP?

Json is stardard format that is human readable used to transmit information from one server to another server. Jsonp is a json with ability to transmit information to another domain. JSONP is JSON with padding, that is, you put a string at the beginning and a pair of parenthesis around it.

Should I use JSONP?

JSONP is not actually JSON with padding, it's Javascript code that's executed. JSON is not a real subset of Javascript and the way it is not is important to us: via UTFGrid, we are all UTF-8 masters. JSONP is not safe: it's Javascript that's executed. It's trivial to XSS with JSONP, because JSONP is XSS.

Is JSONP a security risk?

JSONP is definitely not safe, as it's simply running whatever it gets cross-domain as JavaScript.


2 Answers

Preface:

This answer is over six years old. While the concepts and application of JSONP haven't changed (i.e. the details of the answer are still valid), you should look to use CORS where possible (i.e. your server or API supports it, and the browser support is adequate), as JSONP has inherent security risks.


JSONP (JSON with Padding) is a method commonly used to bypass the cross-domain policies in web browsers. (You are not allowed to make AJAX requests to a web page perceived to be on a different server by the browser.)

JSON and JSONP behave differently on the client and the server. JSONP requests are not dispatched using the XMLHTTPRequest and the associated browser methods. Instead a <script> tag is created, whose source is set to the target URL. This script tag is then added to the DOM (normally inside the <head> element).

JSON Request:

var xhr = new XMLHttpRequest();  xhr.onreadystatechange = function () {   if (xhr.readyState == 4 && xhr.status == 200) {     // success   }; };  xhr.open("GET", "somewhere.php", true); xhr.send(); 

JSONP Request:

var tag = document.createElement("script"); tag.src = 'somewhere_else.php?callback=foo';  document.getElementsByTagName("head")[0].appendChild(tag); 

The difference between a JSON response and a JSONP response is that the JSONP response object is passed as an argument to a callback function.

JSON:

{ "bar": "baz" } 

JSONP:

foo( { "bar": "baz" } ); 

This is why you see JSONP requests containing the callback parameter, so that the server knows the name of the function to wrap the response.

This function must exist in the global scope at the time the <script> tag is evaluated by the browser (once the request has completed).


Another difference to be aware of between the handling of a JSON response and a JSONP response is that any parse errors in a JSON response could be caught by wrapping the attempt to evaluate the responseText in a try/catch statement. Because of the nature of a JSONP response, parse errors in the response will cause an uncatchable JavaScript parse error.

Both formats can implement timeout errors by setting a timeout before initiating the request and clearing the timeout in the response handler.


Using jQuery

The usefulness of using jQuery to make JSONP requests, is that jQuery does all of the work for you in the background.

By default jQuery requires you to include &callback=? in the URL of your AJAX request. jQuery will take the success function you specify, assign it a unique name, and publish it in the global scope. It will then replace the question mark ? in &callback=? with the name it has assigned.


Comparable JSON/JSONP Implementations

The following assumes a response object { "bar" : "baz" }

JSON:

var xhr = new XMLHttpRequest();  xhr.onreadystatechange = function () {   if (xhr.readyState == 4 && xhr.status == 200) {     document.getElementById("output").innerHTML = eval('(' + this.responseText + ')').bar;   }; };  xhr.open("GET", "somewhere.php", true); xhr.send(); 

JSONP:

function foo(response) {   document.getElementById("output").innerHTML = response.bar; };  var tag = document.createElement("script"); tag.src = 'somewhere_else.php?callback=foo';  document.getElementsByTagName("head")[0].appendChild(tag); 
like image 141
Matt Avatar answered Sep 27 '22 21:09

Matt


Say you had some URL that gave you JSON data like:

{'field': 'value'} 

...and you had a similar URL except it used JSONP, to which you passed the callback function name 'myCallback' (usually done by giving it a query parameter called 'callback', e.g. http://example.com/dataSource?callback=myCallback). Then it would return:

myCallback({'field':'value'}) 

...which is not just an object, but is actually code that can be executed. So if you define a function elsewhere in your page called myFunction and execute this script, it will be called with the data from the URL.

The cool thing about this is: you can create a script tag and use your URL (complete with callback parameter) as the src attribute, and the browser will run it. That means you can get around the 'same-origin' security policy (because browsers allow you to run script tags from sources other than the domain of the page).

This is what jQuery does when you make an ajax request (using .ajax with 'jsonp' as the value for the dataType property). E.g.

$.ajax({   url: 'http://example.com/datasource',   dataType: 'jsonp',   success: function(data) {     // your code to handle data here   } }); 

Here, jQuery takes care of the callback function name and query parameter - making the API identical to other ajax calls. But unlike other types of ajax requests, as mentioned, you're not restricted to getting data from the same origin as your page.

like image 20
sje397 Avatar answered Sep 27 '22 20:09

sje397