it-swarm.com.de

Was ist JSONP und warum wurde es erstellt?

Ich verstehe JSON, aber nicht JSONP. Wikipedia-Dokument zu JSON ist (war) das Top-Suchergebnis für JSONP. Es sagt dies:

JSONP oder "JSON with padding" ist eine JSON-Erweiterung, bei der ein Präfix als Eingabeargument des Aufrufs selbst angegeben wird.

Huh? Was für ein Anruf? Das ergibt für mich keinen Sinn. JSON ist ein Datenformat. Da ist kein Anruf.

Das 2. Suchergebnis stammt von einem Typen namens Remy , der folgendes über JSONP schreibt:

JSONP ist eine Skript-Tag-Injektion, bei der die Antwort vom Server an eine vom Benutzer angegebene Funktion übergeben wird.

Ich kann das irgendwie verstehen, aber es ergibt immer noch keinen Sinn.


Was ist JSONP? Warum wurde es erstellt (welches Problem löst es)? Und warum sollte ich es benutzen?


Nachtrag : Ich habe gerade eine neue Seite für JSONP auf Wikipedia erstellt; Es enthält nun eine klare und gründliche Beschreibung von JSONP, basierend auf der Antwort von jvenema .

2005
Cheeso

Es ist eigentlich nicht zu kompliziert ...

Angenommen, Sie befinden sich in der Domäne example.com, und Sie möchten eine Anfrage an die Domäne example.net stellen. . Um dies zu tun, müssen Sie Domänengrenzen überschreiten, ein Nein-Nein in den meisten Browsern.

Das einzige Element, das diese Einschränkung umgeht, sind _<script>_ Tags. Wenn Sie ein Skript-Tag verwenden, wird die Domänenbeschränkung ignoriert, aber unter normalen Umständen können Sie mit den Ergebnissen nicht wirklich etwas anfangen , das Skript wird nur ausgewertet.

Geben Sie JSONP ein. Wenn Sie eine Anfrage an einen JSONP-fähigen Server senden, übergeben Sie einen speziellen Parameter, der dem Server ein wenig über Ihre Seite verrät. Auf diese Weise kann der Server seine Antwort auf eine Weise zusammenfassen, die Ihre Seite verarbeiten kann.

Angenommen, der Server erwartet einen Parameter mit dem Namen callback, um seine JSONP-Funktionen zu aktivieren. Dann würde Ihre Anfrage so aussehen:

_http://www.example.net/sample.aspx?callback=mycallback
_

Ohne JSONP könnte dies ein grundlegendes JavaScript-Objekt wie das folgende zurückgeben:

_{ foo: 'bar' }
_

Wenn der Server in JSONP den Parameter "callback" empfängt, wird das Ergebnis jedoch etwas anders verpackt und in etwa wie folgt zurückgegeben:

_mycallback({ foo: 'bar' });
_

Wie Sie sehen, wird nun die von Ihnen angegebene Methode aufgerufen. So definieren Sie in Ihrer Seite die Rückruffunktion:

_mycallback = function(data){
  alert(data.foo);
};
_

Und jetzt, wenn das Skript geladen ist, wird es ausgewertet und Ihre Funktion wird ausgeführt. Voila, domänenübergreifende Anfragen!

Beachten Sie auch das Hauptproblem bei JSONP: Sie verlieren die Kontrolle über die Anforderung. Zum Beispiel gibt es keine "nette" Möglichkeit, die richtigen Fehlercodes zurückzugewinnen. Infolgedessen verwenden Sie Zeitgeber, um die Anforderung usw. zu überwachen, was immer ein bisschen verdächtig ist. Der Vorschlag für JSONRequest ist eine großartige Lösung, um domänenübergreifendes Scripting zu ermöglichen, die Sicherheit aufrechtzuerhalten und eine ordnungsgemäße Steuerung der Anforderung zu ermöglichen.

In diesen Tagen (2015) ist CORS der empfohlene Ansatz gegenüber JSONRequest. JSONP ist immer noch nützlich für die Unterstützung älterer Browser, aber angesichts der Auswirkungen auf die Sicherheit, es sei denn, Sie haben keine andere Wahl. CORS ist die bessere Wahl.

1949
jvenema

JSONP ist wirklich ein einfacher Trick, um die XMLHttpRequest gleiche Domänenrichtlinie zu überwinden. (Wie Sie wissen, kann man keine AJAX (XMLHttpRequest) Anfrage an eine andere Domain senden.)

Anstatt also XMLHttpRequest zu verwenden, müssen wir script HTML-Tags verwenden, die Sie normalerweise zum Laden von js-Dateien verwenden, damit js Daten von einer anderen Domäne abrufen kann. Klingt komisch?

Es stellt sich heraus, dass Skript Tags auf ähnliche Weise verwendet werden können wie XMLHttpRequest! Überprüfen Sie dies heraus:

script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'http://www.someWebApiServer.com/some-data';

Sie erhalten ein Skript Segment, das nach dem Laden der Daten so aussieht:

<script>
{['some string 1', 'some data', 'whatever data']}
</script>

Dies ist jedoch etwas unpraktisch, da wir dieses Array vom script -Tag abrufen müssen. Also JSONP haben die Macher entschieden, dass dies besser funktioniert (und das ist es):

script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'http://www.someWebApiServer.com/some-data?callback=my_callback';

Beachten Sie die my_callback Funktion dort? Wenn also JSONP server Ihre Anfrage empfängt und den Rückrufparameter findet, gibt er Folgendes zurück, anstatt einfaches js-Array zurückzugeben:

my_callback({['some string 1', 'some data', 'whatever data']});

Sehen Sie, wo der Gewinn liegt: Jetzt erhalten wir einen automatischen Rückruf (my_callback), der ausgelöst wird, sobald wir die Daten erhalten.
Das ist alles, was man über JSONP wissen muss: Es handelt sich um einen Rückruf und Skript-Tags.

HINWEIS: Dies sind einfache Beispiele für die Verwendung von JSONP. Dies sind keine produktionsbereiten Skripte.

Einfaches JavaScript-Beispiel (einfacher Twitter-Feed mit JSONP)

<html>
    <head>
    </head>
    <body>
        <div id = 'twitterFeed'></div>
        <script>
        function myCallback(dataWeGotViaJsonp){
            var text = '';
            var len = dataWeGotViaJsonp.length;
            for(var i=0;i<len;i++){
                twitterEntry = dataWeGotViaJsonp[i];
                text += '<p><img src = "' + twitterEntry.user.profile_image_url_https +'"/>' + twitterEntry['text'] + '</p>'
            }
            document.getElementById('twitterFeed').innerHTML = text;
        }
        </script>
        <script type="text/javascript" src="http://Twitter.com/status/user_timeline/padraicb.json?count=10&callback=myCallback"></script>
    </body>
</html>

Einfaches jQuery-Beispiel (einfacher Twitter-Feed mit JSONP)

<html>
    <head>
        <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
        <script>
            $(document).ready(function(){
                $.ajax({
                    url: 'http://Twitter.com/status/user_timeline/padraicb.json?count=10',
                    dataType: 'jsonp',
                    success: function(dataWeGotViaJsonp){
                        var text = '';
                        var len = dataWeGotViaJsonp.length;
                        for(var i=0;i<len;i++){
                            twitterEntry = dataWeGotViaJsonp[i];
                            text += '<p><img src = "' + twitterEntry.user.profile_image_url_https +'"/>' + twitterEntry['text'] + '</p>'
                        }
                        $('#twitterFeed').html(text);
                    }
                });
            })
        </script>
    </head>
    <body>
        <div id = 'twitterFeed'></div>
    </body>
</html>


JSONP steht für JSON with Padding. (Sehr schlecht benannte Technik, da sie wirklich nichts mit dem zu tun hat, was die meisten Leute als „Polsterung“ bezeichnen würden.)

688
ThatGuy

JSONP erstellt ein "Skript" -Element (entweder in HTML-Markup oder über JavaScript in das DOM eingefügt), das eine Anforderung an einen Remote-Datendienstspeicherort stellt. Die Antwort ist ein in Ihren Browser geladenes Javascript mit dem Namen der vordefinierten Funktion und dem übergebenen Parameter, bei dem es sich um die angeforderten JSON-Daten handelt. Wenn das Skript ausgeführt wird, wird die Funktion zusammen mit JSON-Daten aufgerufen, sodass die anfordernde Seite die Daten empfangen und verarbeiten kann.

Weitere Informationen finden Sie unter: https://blogs.sap.com/2013/07/15/secret-behind-jsonp/

clientseitiges Code-Snippet

    <!DOCTYPE html>
    <html lang="en">
    <head>
     <title>AvLabz - CORS : The Secrets Behind JSONP </title>
     <meta charset="UTF-8" />
    </head>
    <body>
      <input type="text" id="username" placeholder="Enter Your Name"/>
      <button type="submit" onclick="sendRequest()"> Send Request to Server </button>
    <script>
    "use strict";
    //Construct the script tag at Runtime
    function requestServerCall(url) {
      var head = document.head;
      var script = document.createElement("script");

      script.setAttribute("src", url);
      head.appendChild(script);
      head.removeChild(script);
    }

    //Predefined callback function    
    function jsonpCallback(data) {
      alert(data.message); // Response data from the server
    }

    //Reference to the input field
    var username = document.getElementById("username");

    //Send Request to Server
    function sendRequest() {
      // Edit with your Web Service URL
      requestServerCall("http://localhost/PHP_Series/CORS/myService.php?callback=jsonpCallback&message="+username.value+"");
    }    

  </script>
   </body>
   </html>

Serverseitiger Teil von PHP Code

<?php
    header("Content-Type: application/javascript");
    $callback = $_GET["callback"];
    $message = $_GET["message"]." you got a response from server yipeee!!!";
    $jsonResponse = "{\"message\":\"" . $message . "\"}";
    echo $callback . "(" . $jsonResponse . ")";
?>
44
Ajain Vivek

Weil Sie den Server auffordern können, ein Präfix an das zurückgegebene JSON-Objekt anzuhängen. Z.B

function_prefix(json_object);

damit der Browser eval die JSON-Zeichenfolge als Ausdruck "einfügt". Dieser Trick ermöglicht es dem Server, Javascript-Code direkt in den Client-Browser zu "injizieren", und dies unter Umgehung der "Same Origin" -Einschränkungen.

Mit anderen Worten, Sie können domänenübergreifender Datenaustausch haben.


Normalerweise erlaubt XMLHttpRequest keinen domänenübergreifenden Datenaustausch (man muss einen Server in derselben Domäne durchlaufen), während:

<script src="some_other_domain/some_data.js&prefix=function_prefix> `Man kann auf Daten aus einer anderen Domäne als der Origin zugreifen.


Ebenfalls erwähnenswert: Auch wenn der Server als "vertrauenswürdig" eingestuft werden sollte, bevor diese Art von "Trick" ausgeführt wird, können die Nebenwirkungen einer möglichen Änderung des Objektformats usw. enthalten sein. Wenn ein function_prefix (d. H. Eine ordnungsgemäße js-Funktion) zum Empfangen des JSON-Objekts verwendet wird, kann die Funktion Überprüfungen durchführen, bevor die zurückgegebenen Daten akzeptiert/weiterverarbeitet werden.

39
jldupont

JSONP ist eine großartige Lösung, um domänenübergreifende Skriptfehler zu umgehen. Sie können einen JSONP-Dienst ausschließlich mit JS nutzen, ohne auf der Serverseite einen AJAX -Proxy implementieren zu müssen.

Sie können den Dienst b1t.co verwenden, um zu sehen, wie es funktioniert. Dies ist ein kostenloser JSONP-Dienst, mit dem Sie Ihre URLs minimieren können. Hier ist die für den Dienst zu verwendende URL:

http://b1t.co/Site/api/External/MakeUrlWithGet?callback= [resultsCallBack] & url = [escapedUrlToMinify]

Beispiel: Der Aufruf lautet http://b1t.co/Site/api/External/MakeUrlWithGet?callback=whateverJavascriptName&url=google.com

würde zurückkehren

whateverJavascriptName({"success":true,"url":"http://google.com","shortUrl":"http://b1t.co/54"});

Und wenn das in dein js als src geladen wird, wird automatisch whateverJavascriptName ausgeführt, das du als Rückruffunktion implementieren solltest:

function minifyResultsCallBack(data)
{
    document.getElementById("results").innerHTML = JSON.stringify(data);
}

Sie können den JSONP-Aufruf auf verschiedene Arten ausführen (einschließlich der Verwendung von jQuery), aber hier ist ein reines JS-Beispiel:

function minify(urlToMinify)
{
   url = escape(urlToMinify);
   var s = document.createElement('script');
   s.id = 'dynScript';
   s.type='text/javascript';
   s.src = "http://b1t.co/Site/api/External/MakeUrlWithGet?callback=resultsCallBack&url=" + url;
   document.getElementsByTagName('head')[0].appendChild(s);
}

Ein schrittweises Beispiel und ein Jsonp-Webservice zum Üben finden Sie unter: dieser Beitrag

19
dardawk

Ein einfaches Beispiel für die Verwendung von JSONP.

client.html

    <html>
    <head>
   </head>
     body>


    <input type="button" id="001" onclick=gO("getCompany") value="Company"  />
    <input type="button" id="002" onclick=gO("getPosition") value="Position"/>
    <h3>
    <div id="101">

    </div>
    </h3>

    <script type="text/javascript">

    var elem=document.getElementById("101");

    function gO(callback){

    script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = 'http://localhost/test/server.php?callback='+callback;
    elem.appendChild(script);
    elem.removeChild(script);


    }

    function getCompany(data){

    var message="The company you work for is "+data.company +"<img src='"+data.image+"'/   >";
    elem.innerHTML=message;
}

    function getPosition(data){
    var message="The position you are offered is "+data.position;
    elem.innerHTML=message;
    }
    </script>
    </body>
    </html>

server.php

  <?php

    $callback=$_GET["callback"];
    echo $callback;

    if($callback=='getCompany')
    $response="({\"company\":\"Google\",\"image\":\"xyz.jpg\"})";

    else
    $response="({\"position\":\"Development Intern\"})";
    echo $response;

    ?>    
12
sarath joseph

Bevor Sie JSONP verstehen, müssen Sie das JSON-Format und XML kennen. Derzeit ist das im Web am häufigsten verwendete Datenformat XML, XML ist jedoch sehr kompliziert. Es macht es Benutzern unbequem, eingebettete Webseiten zu verarbeiten.

Damit JavaScript auch als Datenverarbeitungsprogramm problemlos Daten austauschen kann, verwenden wir den Wortlaut nach JavaScript-Objekten und haben ein einfaches Datenaustauschformat entwickelt, nämlich JSON. JSON kann als Daten oder als JavaScript-Programm verwendet werden.

JSON kann direkt in JavaScript eingebettet werden. Mit dieser Funktion können Sie bestimmte JSON-Programme direkt ausführen. Aufgrund von Sicherheitsbeschränkungen deaktiviert der Sandbox-Mechanismus des Browsers jedoch die domänenübergreifende Ausführung von JSON-Code.

Damit JSON nach der Ausführung übergeben werden kann, haben wir ein JSONP entwickelt. JSONP umgeht die Sicherheitsgrenzen des Browsers mit der JavaScript-Rückruffunktion und dem <script> -Tag.

Kurz gesagt wird erklärt, was JSONP ist, welches Problem es löst (wann es verwendet werden soll).

10
Marcus Thornton

Die tollen Antworten wurden bereits gegeben, ich muss nur mein Stück in Form von Codeblöcken in Javascript angeben (ich werde auch eine modernere und bessere Lösung für herkunftsübergreifende Anfragen einbinden: CORS mit HTTP-Headern):

JSONP:

1.client_jsonp.js

$.ajax({
    url: "http://api_test_server.proudlygeek.c9.io/?callback=?",
    dataType: "jsonp",
    success: function(data) {
        console.log(data);    
    }
});​​​​​​​​​​​​​​​​​​

2.server_jsonp.js

var http = require("http"),
    url  = require("url");

var server = http.createServer(function(req, res) {

    var callback = url.parse(req.url, true).query.callback || "myCallback";
    console.log(url.parse(req.url, true).query.callback);

    var data = {
        'name': "Gianpiero",
        'last': "Fiorelli",
        'age': 37
    };

    data = callback + '(' + JSON.stringify(data) + ');';

    res.writeHead(200, {'Content-Type': 'application/json'});
    res.end(data);
});

server.listen(process.env.PORT, process.env.IP);

console.log('Server running at '  + process.env.PORT + ':' + process.env.IP);

CORS:

3.client_cors.js

$.ajax({
    url: "http://api_test_server.proudlygeek.c9.io/",
    success: function(data) {
        console.log(data);    
    }
});​

4.server_cors.js

var http = require("http"),
    url  = require("url");

var server = http.createServer(function(req, res) {
    console.log(req.headers);

    var data = {
        'name': "Gianpiero",
        'last': "Fiorelli",
        'age': 37
    };

    res.writeHead(200, {
        'Content-Type': 'application/json',
        'Access-Control-Allow-Origin': '*'
    });

    res.end(JSON.stringify(data));
});

server.listen(process.env.PORT, process.env.IP);

console.log('Server running at '  + process.env.PORT + ':' + process.env.IP);
3
Humoyun Ahmad