Gepost op

Wat is JSONP?

JSONP is een manier om met JavaScript Cross-Origin Requests te doen. Dat wil zeggen om requests te doen naar een server binnen een ander (sub)domein dan het huidige. Dit is namelijk met een standaard XMLHttpRequest niet mogelijk wegens veiligheidsoverwegingen. In nieuwe browsers is dit probleem opgelost door de implementatie van Cross-origin resource sharing (CORS). De implementatie  van CORS vraagt echter om complexere aanpassingen van je webservice dan JSONP en wordt bovendien niet ondersteunt door oude browsers en veel mobiele browsers. Veel webservices maken daarom nog steeds gebruik van JSONP om Cross-Origin Requests af te handelen.

Wanneer jQuery wordt gebruikt is de implementatie van JSONP erg simpel. Door simpelweg ?callback=? toe te voegen aan een request maak je van een normaal JSON request een JSONP request.

// standaard JSON request naar een eigen webservice
var my_webservice = 'www.my_own_domain.com/webservice';
var req = $.getJSON(my_webservice);

// standaard JSONP request naar een webservice buiten het eigen domein
var not_my_webservice = 'www.not_my_own_domain.com/webservice';
var req = $.getJSON(not_my_webservice + '?callback=?');

JSONP heeft enkel een aantal beperkingen ten opzichte van een normaal XMLHttpRequest en het is daarom goed om te begrijpen wat er gebeurt.

Daar een standaard XMLHttpRequest dus niet werkt wordt er bij JSONP een ‘trucje’ toegepast. Het request naar de externe webserver wordt gedaan door het laden van een extern script. In de querystring van de locatie van het externe script kunnen variabelen aan het request worden meegegeven. De webservice geeft vervolgens zijn antwoord op het request terug in het geladen script. Een implementatie in Vanilla JavaScript zou er zo uit kunnen zien.

// De callback functie die wordt aangeroepen, zodra het script is geladen.
var foo = function(response) {
  // Hier kun je iets met het antwoord van de webservice gaan doen
}

// De externe webservice. In de querystring wordt de naam van de callback functie meegeven,
// zodat de teruggegeven data hierin kan worden gewrapped. De JSON krijgt Padding, oftewel JSONP.
var not_my_webservice = 'www.not_my_own_domain.com/webservice?callback=foo'

// Initialiseer het script element
var script = document.createElement('script');
script.src = not_my_webservice;
script.type = 'text/javascript';
script.charset = 'utf-8';
script.async = true

// Injecteer het script in de head van pagina.
var head = document.getElementsByTagName('head')[0];
head.appendChild(script);

Het antwoord van de webservice ziet er dan bijvoorbeeld zo uit:

foo({some_key: some_value})

Zodra het script geladen is zal dus de callback functie worden uitgevoerd waarbij de data als argument aan de functie wordt meegegeven. In deze callback-functie kun je vervolgens iets gaan doen met de data.

Door het mechanisme achter JSONP te snappen zie je ook direct de beperkingen. Zo is het bijvoorbeeld enkel mogelijk om GET-requests te doen en is er niet de mogelijk voor error handling. Een 404 van de webservice wordt hierdoor bijvoorbeeld niet ondervangen. Nu begrijp je dus ook waarom het volgende stukje code met jQuery niet zal werken.

var not_my_webservice = 'www.not_my_own_domain.com/webservice';
var req = $.getJSON(not_my_webservice + '?callback=?');
req.error(function() {
  // Deze code zal nooit worden uitgevoerd.
});