web-dev-qa-db-fra.com

JavaScript: Comment créer du JSONP?

J'ai deux domaines, exemple1.com et exemple2.com

De example1.com, j'aimerais appeler une API JSON que j'ai sur example2.com. Sachant que cela n’est pas permis, j’ai eu l’impression - c’est exactement pourquoi JSONPa été créé.

La question est, comment puis-je modifier mon API JSON pour le rendre compatible JSONP?

Fondamentalement, comment créer l’API de rappel?

METTRE À JOUR

Ma langue côté serveur est PHP

40
Teddi

C'est simple. Acceptez simplement un paramètre appelé callback dans GET.

Enroulez ensuite la fonction JavaScript de rappel autour de vos données.

Exemple en 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;
}

L'idée est de simplement renvoyer un fichier JavaScript qui appelle la fonction de rappel avec l'objet JSON en tant que premier paramètre de la fonction de rappel JavaScript.

Vous pouvez utiliser la fonction json_encode() intégrée pour créer des chaînes JSON (que contient $data dans notre exemple ci-dessus) à partir de tableaux et d'objets en PHP. 

Pour utiliser le service JSONP, vous pouvez utiliser la balise <script>:

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

Vous avez besoin d'un langage côté serveur, le paramètre de rappel est simplement un paramètre GET, vous lisez le paramètre, vous enroulez la réponse JSON dans un appel de fonction et vous l'imprimez comme ceci callback(jsonResponse);.

Je vous laisse un exemple vraiment minimaliste utilisant Python puisque vous ne mentionnez aucun langage côté serveur:

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

C'est le code d'un petit service JSONP utilisé pour extraire l'adresse IP du client créée par Zach et il est hébergé sur le Google App Engine .

26
CMS

Mauris vous a déjà donné un exemple de travail. J'ajouterai seulement que vous devriez vérifier si un paramètre callback est présent et non vide, et si ce n'est pas le cas, renvoyer les données json telles quelles sans les parenthèses. Donc, fondamentalement, votre api sera JSON avec la possibilité d’être JSON-P lorsque callback est donné.

Pour utiliser le service Web JSON-P, vous pouvez créer un noeud de script de manière dynamique et définir un attribut src de manière à pointer vers le service Web, à moins que vous n'utilisiez un cadre tel que YUI ou jQuery. N'oubliez pas de supprimer le noeud du dom avant de le répéter, car ce noeud de script dynamique est à usage unique.

6
Joy Dutta

Je sais que je suis en retard pour le parti, et l'une des réponses a été faite à propos de la sécurité du code. Voici un bon article à ce sujet: 

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

Et voici le code que vous devriez utiliser: 

<?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);
4
jkinz
// Adds script tag to head of the page
function addScriptToHead(source, code, type) {
    var script = document.createElement('script');
    if (type === 'js') {
        script.setAttribute('type', 'text/javascript');
    }
    if (source !== '') {
        script.setAttribute('src', source);
    }
    if (code !== '') {
        if (document.all && !window.opera)  {
            script.text = code;
        } else {
            script.innerHTML = code;
        }
    }
    document.getElementsByTagName('head')[0].appendChild(script);
}


// Callback function
function addScriptToHead(any_param) {

// do whatever needs to be done

}

//call example

addScriptToHead('http://url_to_receiver_script/index.php&param=anything', '', 'js');

/// le script de rappel doit renvoyer le nom de la fonction de rappel, c'est-à-dire si vous tapez dans le navigateur

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

il devrait renvoyer juste un texte (nom de la fonction de traitement existante): addScriptToHead (any_param)

fonctionne comme une horloge dans n'importe quel navigateur.

3
Dmitriy Naumov

Facile avec jQuery, C'est le côté client:

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

Et assurez-vous d’obtenir le bon json du côté serveur; 
et n'oubliez pas de renvoyer le paramètre jsonp_callback, sinon cela ne fonctionnera pas !!!!!
et c'est tout.

2
Tom

exemple ici __. http://www.insideria.com/2009/03/what-in-the-heck-is-jsonp-and.html

<script src=".../example2...?output=json;callback=loadit"></script>
<script>
alert( "I got this from example2 " + loadit);
</script>
0
asdf

Vous pouvez utiliser le JSON simple pour PHP pour le falsifier! Cela simplifie tout!

<?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();
?>
0
Alexis Paques