Что такое JSONP и чем он отличатеся от JSON

JSON - это просто формат данных. JSONP - это методология использования этого формата в кросс-доменных запросах.

JSONP - это старый трюк, придуманный для обхода ограничения безопасности в веб-браузерах, которое запрещает нам получать данные, находящиеся на другом сайте/сервере.

JSONP расшифровывается как JSON with Padding.

JSONP запрос

Идея заключается в том, что вместо использования ajax для запроса данных, мы используем тег <script src="externalURL">. В src указанном в скрипте наша страница получает и запускает JS код.

Сервер на который был отправлен такой запрос должен отдать нам правильный JS код (JSONP ответ). В этом ответе сервер вместо JSON стоки, отдает JS код, где JSON данные передаются как параметр функции (какое название будет у функции мы указываем в URL). На своей стороне мы создаем JS функцию, которая по итогу будет запущена после того как придет ответ с удаленного сервера.

Получается что при загрузке и выполнении скрипта у нас запускается js функция, где первый параметр - это JSON объект полученный с удаленного сервера. В этой функции мы и обрабатываем полученные с другого сервера данные.

Рассмотрим на примере

Допустим, наш домен example.com и мы хотим сделать запрос на домен example.net. Для этого нам нужно пересечь границы нашего домена, а это запрещено в большинстве браузеров. Единственный элемент, который обходит это ограничение - это тег <script>.

Когда мы делаем запрос на сервер (через тег <script>), который поддерживает JSONP, мы передаем специальный параметр, который сообщает серверу название нашей JS функции, которую нужно запустить. Таким образом, удаленный сервер может завернуть свой JSON в функцию и вернуть там готовый JS код, который будет запущен на нашей странице.

Допустим, сервер ожидает параметр _jsonp, чтобы включить JSONP. Тогда наш URL (запрос) будет выглядеть следующим образом:

http://www.example.net/sample.aspx?_jsonp=myCallback

Без ?_jsonp=myCallback сервер бы вернул JSON строку, например:

{ "foo": "bar" }

Однако, когда сервер получает параметр "_jsonp", он расценивает запрос как JSONP и формирует результат по-другому, возвращая:

myCallback( { foo: "bar" } );

На своей странице мы создаем такую функцию-обработчик:

function myCallback( data ){
	alert( data.foo )
}

Теперь, когда скрипт будет загружен - он будет выполнен у нас, т.е. сработает наша js функция с данными JSON от удаленного сервера.

Вуаля, кросс-доменный запрос выполнен!

Пример кода с JSONP запросом

Базовый пример JavaScript (лента Twitter с использованием 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 src="http://twitter.com/status/user_timeline/padraicb.json?count=10&callback=myCallback"></script>
	</body>

</html>

Проблемы (недостатки)

  • С JSONP у нас нет нормального контроля над запросом. Например, не существует нормального способа получить код ошибки. В результате нам, например, нужно будет использовать таймеры для контроля запроса и т.д.

  • Использование JSONP небезопасно. Поскольку JSONP - это фактически javascript, он может делать все, что может делать javascript, поэтому мы должны полностью доверять поставщику данных JSONP, потому что мы запускаем чужой JS-код, который может быть изменен на вредоносный в любой момент.

  • Мы можем выполнять только GET-запросы.

Есть предложение JSONRequest, которое вроде как должно решить проблему меж-доменных запросов, безопасности и обеспечения надлежащего контроля над запросом.

Рекомендация - Не используйте JSONP, используйте CORS

Сегодня CORS является рекомендуемым подходом для выполнения кросс-доменных запросов. JSONP все еще полезен для поддержки старых браузеров, но, учитывая безопасность - CORS - лучший выбор.

Кроме того, политика безопасности Same-Origin применяется не только к JSON данным, но и к любым другим: WebFonts, изображения/видео, нарисованные с помощью drawImage()...

Читайте о CORS здесь: https://developer.mozilla.org/ru-RU/docs/Web/HTTP/CORS Суть коротко:

Cross-Origin Resource Sharing (CORS) - это механизм, который использует дополнительные HTTP-заголовки, чтобы сообщить браузерам о предоставлении веб-приложению, запущенному в одном месте, доступа к выбранным ресурсам из другого места.

Веб-приложение выполняет кросс-доменный HTTP-запрос всегда, когда запрашивает ресурс, который имеет отличное от его собственного происхождение (домен, протокол или порт).

WordPress функции связанные с JSONP

wp_is_jsonp_request()
Проверяет, является ли текущий запрос запросом JSONP или ожидает ответа JSONP.
wp_check_jsonp_callback()
Checks that a JSONP callback is a valid JavaScript callback name.
_jsonp_wp_die_handler()
Kills WordPress execution and displays JSONP response with an error message.