2009-11-05 16 views
39

Ich habe zwei Domänen, example1.com und example2.comJavaScript: Wie erstelle ich JSONP?

Von example1.com möchte ich eine JSON API aufrufen, die ich auf example2.com habe. Zu wissen, dass dies nicht erlaubt ist, ist mir aufgefallen - genau deshalb wurde JSON P erstellt.

Frage ist, wie ändere ich meine JSON API, um es JSONP fähig zu machen?

Grundsätzlich, wie erstelle ich die Callback API?

UPDATE

Meine serverseitige Sprache ist PHP

Antwort

26

Sie benötigen eine Server-Side-Sprache, die Callback-Parameter einfach ein GET-Parameter sind , lesen Sie den Parameter und wickeln Sie die JSON-Antwort in einen Funktionsaufruf und Sie drucken es wie folgt callback(jsonResponse);.

lasse ich euch ein wirklich minimalistisches Beispiel Python verwenden, da Sie keine serverseitige Sprache erwähnen:

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 

, dass der Code einer kleinen JSONP service ist verwendet, um die Client-IP-Adresse aus abgerufen wird durch Zach und es ist auf der Google App Engine gehostet.

+0

Ihr Code arbeitete schön und ist so elegant! – TruMan1

+0

Diese Antwort sollte akzeptiert werden –

73

Es ist einfach. Übernehmen Sie einfach einen Parameter namens callback im GET.

Dann wickeln Sie die Callback-JavaScript-Funktion um Ihre Daten.

Beispiel in PHP:

<?php 

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

if(array_key_exists('callback', $_GET)){ 

    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']; 
    echo $callback.'('.$data.');'; 

}else{ 
    // normal JSON string 
    header('Content-Type: application/json; charset=utf8'); 

    echo $data; 
} 

Es Idee ist, einfach eine JavaScript-Datei zurück, die die Callback-Funktion mit dem JSON-Objekt als erste Parameter der JavaScript-Callback-Funktion aufruft.

Mit der integrierten json_encode()-Funktion können Sie JSON-Strings (die in unserem obigen Beispiel $data enthalten) aus Arrays und Objekten in PHP erstellen.

den JSONP Service zu nutzen, können Sie die <script>-Tag verwenden:

<script> 
    function receiver(data){ 
     console.log(data); 
    } 
</script> 
<script src="data-service.php?callback=receiver"></script> 
+4

Wow, ist es wirklich nur so einfach? – Teddi

+0

Muss ich hinzufügen: echo 'Zugriffssteuerung-Erlauben-Ursprung: *' echo 'Zugriffssteuerungs-Erlauben-Methoden: GET' ??? – Teddi

+0

@Teddi: Diese Header unterstützen die kommende XMLHttpRequest 2 Spezifikation (http://www.w3.org/TR/access-control/) und BTW funktionieren bereits auf Firefox 3.5 (https://developer.mozilla.org/de/HTTP_access_control) – CMS

6

Mauris gab bereits ein funktionierendes Beispiel. Ich würde nur hinzufügen, dass Sie überprüfen sollten, ob ein callback Parameter vorhanden und nicht leer ist, und wenn nicht, geben Sie die JSON-Daten so zurück, wie es ohne die Klammern ist. Im Grunde wird Ihre API JSON mit der Angabe JSON-P sein, wenn callback angegeben wird.

Um den JSON-P-Webservice zu verwenden, können Sie, sofern Sie kein Framework wie YUI oder jQuery verwenden, einen Skriptknoten dynamisch erstellen und sein src-Attribut auf den Webservice verweisen. Denken Sie daran, den Knoten aus dem Dom zu entfernen, bevor Sie ihn erneut ausführen, da dieser dynamische Skriptknoten nur zur einmaligen Verwendung dient.

2

einfach mit jQuery, , dass die Client-Seite ist:

$.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]); 
    } 
} 
} 

Und achten Sie darauf, dass Sie die richtige json von der Serverseite erhalten;
und vergessen Sie nicht, den jsonp_callback param zurückzugeben, sonst wird es nicht funktionieren !!!!!
und das war es wirklich.

3

/// der Callback-Skript sollten Namen der Callback-Funktion zurückzukehren, das heißt, wenn Sie in Browser eingeben

http://url_to_receiver_script/index.php&param=anything

es sollte nur einen Text (Name der bestehenden Verarbeitungsfunktion) zurück: addScriptToHead (any_param)

funktioniert wie eine Uhr in jedem Browser.

4

Ich weiß, ich bin zu spät zur Party, und es gab einen Kommentar über die Sicherheit des Codes in einer der Antworten. Hier ist ein guter Artikel dazu:

http://www.geekality.net/2010/06/27/php-how-to-easily-provide-json-and-jsonp/

Und hier ist der Code, den Sie laufen sollte:

<?php header('content-type: application/json; charset=utf-8'); 

function is_valid_callback($subject) 
{ 
    $identifier_syntax 
     = '/^[$_\p{L}][$_\p{L}\p{Mn}\p{Mc}\p{Nd}\p{Pc}\x{200C}\x{200D}]*+$/u'; 

    $reserved_words = array('break', 'do', 'instanceof', 'typeof', 'case', 
     'else', 'new', 'var', 'catch', 'finally', 'return', 'void', 'continue', 
     'for', 'switch', 'while', 'debugger', 'function', 'this', 'with', 
     'default', 'if', 'throw', 'delete', 'in', 'try', 'class', 'enum', 
     'extends', 'super', 'const', 'export', 'import', 'implements', 'let', 
     'private', 'public', 'yield', 'interface', 'package', 'protected', 
     'static', 'null', 'true', 'false'); 

    return preg_match($identifier_syntax, $subject) 
     && ! in_array(mb_strtolower($subject, 'UTF-8'), $reserved_words); 
} 

$data = array(1, 2, 3, 4, 5, 6, 7, 8, 9); 
$json = json_encode($data); 

# JSON if no callback 
if(! isset($_GET['callback'])) 
    exit($json); 

# JSONP if valid callback 
if(is_valid_callback($_GET['callback'])) 
    exit("{$_GET['callback']}($json)"); 

# Otherwise, bad request 
header('status: 400 Bad Request', true, 400); 
+0

Wenn zufällig Winkel verwendet wird, wird dies nicht funktionieren. Angular unterstützt jsonp, ersetzt aber den Callback durch etwas wie angle.callback._0. Würde ein Rückruf wie dieser unsicher sein? –

+0

@BobVork Ich glaube nicht, Sie können die '$ identifier_syntax 'so ändern, dass sie auch Perioden enthält. Tatsächlich glaube ich, dass ich das aus genau diesem Grund in meiner Implementierung getan habe (aber dies gepostet habe, bevor ich meine Implementierung beendet hatte). – jkinz

0

Sie können die Simple JSON for PHP verwenden es zu schmieden! Es vereinfacht alles!

<?php 

    include('../includes/json.php'); 

    $json = new json('callback', 'myCallback'); 

    $object = new stdClass(); 
    $object->FirstName = 'John'; 
    $object->LastName = 'Doe'; 
    $array = array(1,'2', 'Pieter', true); 
    $jsonOnly = '{"Hello" : "darling"}'; 
    // Add objects to send 
    $json->add('status', '200'); 
    $json->add("worked"); 
    $json->add("things", false); 
    $json->add('friend', $object); 
    $json->add("arrays", $array); 
    $json->add("json", $jsonOnly, false); 

    /* 
    Expected result : 
    myCallback({ 
    "status": "200", 
    "worked": true, 
    "things": false, 
    "friend": { 
     "FirstName": "John", 
     "LastName": "Doe" 
    }, 
    "arrays": [ 
     1, 
     "2", 
     "Pieter", 
     true 
    ], 
    "json": { 
     "Hello": "darling" 
    } 
    }); 

    */ 
    $json->send(); 
?>