У меня есть два домена, example1.com и example2.com
Из example1.com, я хотел бы назвать JSON API, который у меня есть на example2.com. Зная, что это не разрешено, мне пришло в голову – именно поэтому был создан JSON P.
Вопрос в том, как мне изменить свой JSON API, чтобы сделать его JSONP способным?
В принципе, как мне создать обратный вызов api?
ОБНОВИТЬ
Мой серверный язык – это PHP
Это просто. Просто примите параметр, называемый callback
в GET.
Затем заверните функцию JavaScript обратного вызова вокруг ваших данных.
Пример в 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; }
Идея состоит в том, чтобы просто вернуть файл JavaScript, который вызывает функцию обратного вызова с объектом JSON в качестве первого параметра функции обратного вызова JavaScript.
Вы можете использовать встроенную функцию json_encode()
для создания строк JSON (которые содержат $data
в нашем примере выше) из массивов и объектов в PHP.
Чтобы использовать службу JSONP, вы можете использовать <script>
:
<script> function receiver(data){ console.log(data); } </script> <script src="data-service.php?callback=receiver"></script>
Вам нужен серверный язык, параметр обратного вызова – это просто параметр GET, вы читаете параметр, и вы переносите ответ JSON в вызов функции, и вы печатаете его, как этот callback(jsonResponse);
,
Я оставляю вам действительно минималистский пример с использованием Python, так как вы не упоминаете серверный язык:
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
Это код небольшой службы JSONP, используемой для получения IP-адреса клиента, сделанного Zach, и он размещен в Google App Engine .
Маурис уже дал вам рабочий пример. Я бы добавил, что вы должны проверить, присутствует ли параметр callback
и не пуст, а если нет, верните json-данные, как есть без круглых скобок. Таким образом, в основном ваш api будет JSON с предоставлением JSON-P, когда предоставляется callback
.
Чтобы использовать веб-сервис JSON-P, если вы не используете фреймворк, такой как YUI или jQuery, вы можете просто создать узел сценария динамически и установить его атрибут src
чтобы указать на веб-сервис. Не забудьте удалить узел из dom, прежде чем повторять его снова, поскольку этот динамический узел сценария используется только один раз.
Я знаю, что опаздываю на вечеринку, и в одном из ответов был комментарий о безопасности кода. Вот хорошая статья об этом:
http://www.geekality.net/2010/06/27/php-how-to-easily-provide-json-and-jsonp/
И вот код, который вы должны запустить:
<?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);
// 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¶m=anything', '', 'js');
/// сценарий обратного вызова должен возвращать имя функции обратного вызова, т. е. если вы вводите браузер
Http: //url_to_receiver_script/index.php¶m=anything
он должен возвращать только текст (имя существующей функции обработки): addScriptToHead (any_param)
работает как часы в любом браузере.
Легко с jQuery, то есть с клиентской стороны:
$.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]); } } }
И убедитесь, что вы получаете правильный json с серверной стороны;
и не забудьте вернуть параметр jsonp_callback, иначе это не сработает !!!!!
и это действительно так.
пример здесь 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>
Вы можете использовать Simple JSON для PHP, чтобы подделать его! Это упрощает все!
<?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(); ?>