Oder: Wie man mit Javascript doch auf andere Domains zugreifen kann, wenn Sie einen lassen.
Wer kennt das nicht: Man programmiert ein Frontend, welches irgendwo auf eine entfernte JSON-API zugreift, man entwickelt lokal und alles funktioniert super. Aliase im Apache, Proxy-Scripte und Co. funktionieren super.
Wenn man die Anwendung online dann stellt, eventuell beim Kunden, ist alles anders. Ein Lostopf der (Un-)Möglichkeiten. Man nicht mehr Admin und kann nicht mehr ganz so einfach tun und lassen was man will. Soll die Anwendung beispielsweise auf Shared-Hosting-Servern laufen, fallen Apache-Seitige Aliase in der Regel als erstes weg. Je nachdem, was der Hoster an Apache-Modulen bietet, kann man hier eventuell noch einen Rewrite-Proxy mit .htaccess
-Dateien zusammenbauen. Welche Vor- und Nachteile das mit sich bringt, muss jeder für sich selbst abwägen.
Damit kann man noch ein paar Probleme abfangen. Interessant wird es bei Billig-Hostern (die so billig nicht sein müssen), wenn einige Funktionen nicht vorhanden sind. mod_proxy
und mod_rewrite
werden von einigen Hostern als “zu sicherheitskritisch” angesehen und damit der Kundschaft nicht zu Verfügung gestellt.
Gut. Bliebe noch ein lokales Proxy-Script. Ein kleines Script für PHP/ASP/node.js, welches Zugriffe auf eine andere Domain durchschleift. Das wird aber nicht immer ermöglicht. Auch hier müssen potentielle Sicherheitslücken kalkuliert werden. Manche Provider erlauben daher keinen Zugriff von PHP auf andere Domains, weder via PHP, noch via fopen oder curl.
Hier kommen die Entwickler der Webservices ins Spiel
Nimmt man an, man hat das Backend der Applikation (das Script, welches das JSON liefert) auf einem anderen Server als das Frontend. Wenn man ein Betreiber wie z.b. Flickr, Twitter oder Github ist, der eine Rest-API hat, die JSON ausgibt, dann hier mein Appell: Bietet JSONP an!
JSONP unterscheidet sich nicht großartig von JSON. Das “P” steht dabei für “Padding”, also “JSON with Padding“. Übersetzt etwa: “JSON mit Polster”. Das “Polster” besteht hier im Endeffekt aus einem Funktionsnamen.
//JSON
{
"key1": "value1",
"key2": "value2"
}
//JSONP
functionsname({
"key1": "value1",
"key2": "value2"
});
Das ist auch halb so schwer, in PHP könnte sowas z.B. folgendermaßen aussehen:
Wichtig ist hierbei, dass der JSONP-Parameter definiert ist. Aber das kann man als Anbieter ja durchaus vorher ansagen, wie der Parameter benutzt werden soll.
Bei Google Maps sieht der JSONP-Response übrigens so aus:
functionname && functionsname({
"key1": "value1",
"key2": "value2"
});
Damit wird verhindert, dass beim Panning Daten ausgeführt werden, die schon vorbeigescrollt sind. Denn dann ist die Callback-Funktion ja nicht mehr vorhanden (im besten Fall).
Wie funktioniert JSONP?
Ein normaler JSON-Request ist ein XMLHttpRequest. Diese haben die Besonderheit, dass Sie auf eine bestimmte Domain, nämlich die aufrufende, beschränkt sind. Auch Subdomains sind nur mit Tricks möglich. Das Einbinden von "normalen" Javascripten und das Ausführen dieser von fremden Domains ist jedoch möglich. Der Ausführungskontext ist aber immer die Domain, auf der das Script eingebunden ist, niemals die, von der das Script kommt.
Das wäre ja auch schön blöd. Bindet man ein JS von Google ein, sollte man ja keinen Zugriff auf die Daten bei Google bekommen.
JSONP funktioniert nun genauso. Es wird kein XMLHttpRequest gestellt, sondern ein externes Script geladen. Vorher wird eine virtuelle Callbackfunktion erstellt. Das nachgeladene Skript wird nach dem erfolgreichen Laden ausgeführt. Im Fall von JSONP bedeutet das, dass eine Funktion aufgerufen wird. Übergabeparameter an die Funktion ist der eigentliche JSON-Response. Damit schließt sich der Kreis.
[yellow_box]Bitte, liebe Entwickler, wenn ihr JSON anbietet, baut JSONP-Unterstützung gleich mit dazu. So schwer ist das nicht. Damit ermöglicht ihr aber einen JS-Zugriff auf eure API. Das ist sicher für den einen oder anderen nützlich...[/yellow_box]