JavaScript: comment créer JSONP?

j'ai deux domaines, example1.com et example2.com

de example1.com, je voudrais appeler une API JSON que j'ai sur example2.com. Sachant que cela n'est pas permis, il m'est venu à l'esprit - c'est exactement pourquoi JSON P a été créé.

la Question Est, comment modifier mon API JSON pour la rendre capable de JSONP?

en gros, comment créer l'api de rappel?

UPDATE

mon langage côté serveur est PHP

40
demandé sur Rudey 2009-11-05 06:44:29

8 réponses

c'est simple. Il suffit d'accepter un paramètre appelé callback dans L'GET.

ensuite envelopper la fonction de rappel JavaScript 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 retourner un fichier JavaScript qui appelle la fonction callback avec l'objet JSON comme premier paramètre de la fonction JavaScript callback.

vous pouvez utiliser la fonction intégrée json_encode() pour créer des chaînes JSON (que $data dans notre exemple ci-dessus contient) à 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
répondu mauris 2012-12-02 22:35:39

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

je vous laisse un exemple vraiment minimaliste en 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

qui est le code d'un petit JSONP service utilisé pour récupérer l'adresse IP du client faite par Zach et il est hébergé sur le Google App Engine .

26
répondu CMS 2017-05-23 11:46:39

Mauris vous a déjà donné un exemple. Je voudrais seulement ajouter que vous devriez vérifier si un callback param est présent et non vide, et si non, renvoyer les données json comme c'est sans les parenthèses. Donc en gros votre api sera JSON avec la disposition D'être JSON-P quand callback est donné.

pour consommer le webservice JSON-P, sauf si vous utilisez un framework comme YUI ou jQuery, vous pouvez simplement créer un noeud de script dynamiquement et définir son attribut src pour pointer vers le webservice. N'oubliez pas de retirer le noeud du dom avant de le répéter à nouveau, puisque ce noeud de script dynamique n'est utilisé qu'une seule fois.

6
répondu Joy Dutta 2009-11-05 04:59:59

je sais que je suis en retard à la fête, et il y avait un commentaire sur la sécurité du code dans l'une des réponses. 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 devez exécuter:

<?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
répondu jkinz 2013-08-13 17:36:56
// 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 retourner le nom de la fonction de rappel, c.-à-d. Si vous tapez dans le navigateur

http://url_to_receiver_script/index.php¶m=rien

il doit retourner juste un texte(Nom de la fonction de traitement existante): addScriptToHead (any_param)

fonctionne comme une horloge dans n'importe quel navigateur.

3
répondu Dmitriy Naumov 2011-03-25 16:08:04

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 que vous obtenez JSON approprié du côté du serveur;

et n'oubliez pas de rendre le param jsonp_callback, sinon ça ne marchera pas!!!!!

et qui est-il vraiment.

2
répondu Tom 2009-11-18 01:12:53

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

<script src=".../example2...?output=json;callback=loadit"></script>
<script>
alert( "I got this from example2 " + loadit);
</script>
0
répondu asdf 2009-11-05 03:53:58

vous pouvez utiliser le JSON Simple pour PHP pour le forger! Il simplifier les choses!

<?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
répondu Alexis Paques 2015-04-27 16:58:51