TL; DR
JSONP - это старый прием, изобретенный для обхода ограничения безопасности, которое запрещает нам получать данные JSON с другого сервера (другого источника * ).
Трюк работает с использованием <script>
тега, который запрашивает JSON из этого места, например:, { "user":"Smith" }
но обернут в функцию, фактический JSONP («JSON with Padding»):
peopleDataJSONP({"user":"Smith"})
Получение этого в этой форме позволяет нам использовать данные в нашей peopleDataJSONP
функции. JSONP - плохая практика , не используйте ее (читайте ниже)
Проблема
Скажем, мы находимся ourweb.com
и хотим получать данные JSON (или любые необработанные данные) anotherweb.com
. Если бы мы использовали запрос GET (например XMLHttpRequest
, fetch
вызов $.ajax
и т. Д.), Наш браузер сказал бы, что это не разрешено с этой ужасной ошибкой:
Как получить данные, которые мы хотим? Ну, <script>
теги не подчиняются всему этому ограничению сервера (origin *)! Вот почему мы можем загрузить библиотеку, такую как jQuery или Google Maps, с любого сервера, например, CDN, без каких-либо ошибок.
Важный момент : если вы подумаете об этом, эти библиотеки - это реально работающий JS-код (обычно это огромная функция со всей логикой внутри). Но необработанные данные? Данные JSON не являются кодом . Там нет ничего, чтобы бежать; это просто простые данные.
Таким образом, мы не можем обрабатывать или манипулировать нашими ценными данными. Браузер загрузит данные, на которые указывает наш <script>
тег, и при обработке будет по праву жаловаться:
WTF это {"user":"Smith"}
дерьмо мы загрузили? Это не код Я не могу вычислить, синтаксическая ошибка!
Взлом JSONP
Старый / хакерский способ использовать эти данные? Нам нужен этот сервер для отправки его с некоторой логикой, поэтому, когда он будет загружен, ваш код в браузере сможет использовать эти данные. Таким образом, сторонний сервер отправляет нам данные JSON внутри функции JS. Сами данные устанавливаются как входные данные этой функции. Это выглядит так:
peopleDataJSONP({"user":"Smith"})
что делает его JS-кодом, наш браузер будет анализировать без жалоб! Точно так же, как это происходит с библиотекой jQuery. Теперь, чтобы получить это, клиент «запрашивает» JSON-дружественный сервер для него, обычно это делается так:
<script src="https://anotherweb.com/api/data-from-people.json?myCallback=peopleDataJSONP"></script>
Наш браузер получит JSONP с таким именем функции, поэтому нам нужна функция с таким же именем в нашем коде, например:
const peopleDataJSONP = function(data){
alert(data.user); // "Smith"
}
Или вот так, тот же результат:
function peopleDataJSONP(data){
alert(data.user); // "Smith"
}
Браузер загрузит JSONP и запустит его, который вызывает нашу функцию , где аргументом data
будет наш JSON. Теперь мы можем делать с нашими данными все, что захотим.
Не используйте JSONP, используйте CORS
JSONP - это хакерский сайт с несколькими недостатками:
- Мы можем только выполнять запросы GET
- Поскольку это запрос GET, запускаемый простым тегом скрипта, мы не получаем полезных ошибок или информации о ходе выполнения.
- Есть также некоторые проблемы с безопасностью, такие как запуск JS-кода вашего клиента, который может быть изменен на вредоносную полезную нагрузку.
- Это только решает проблему с данными JSON, но политика безопасности Same-Origin применяется к другим данным (веб-шрифты, изображения / видео, нарисованные с помощью drawImage () ...)
- Это не очень элегантно и не читабельно.
Вывод заключается в том, что в настоящее время нет необходимости использовать его .
JSONP - это хитрость для получения данных JSON с другого сервера, но мы будем нарушать тот же принцип безопасности (Same-Origin), если нам понадобятся другие виды межсайтового контента.
Вы должны прочитать о CORS здесь , но суть этого:
Распределение ресурсов между источниками (CORS) - это механизм, который использует дополнительные заголовки HTTP, чтобы дать браузерам указание предоставить веб-приложению, работающему с одним источником, доступ к выбранным ресурсам из другого источника. Веб-приложение выполняет HTTP-запрос перекрестного источника, когда оно запрашивает ресурс, который имеет другой источник (домен, протокол или порт) от своего собственного.
* происхождение определяется 3 вещами: протокол , порт и хост . Так, например, https://web.com
источник отличается от http://web.com
(другой протокол) и https://web.com:8081
(другой порт) и, очевидно, https://thatotherweb.net
(другой хост)