Avatar ·

Что такое JSONP и зачем он был создан? Объясните простыми словами с примерами

Всем привет! Я начинающий фронтенд-разработчик и пытаюсь разобраться с темой кросс-доменных запросов. Я знаю, что есть CORS, но наткнулся на упоминание JSONP в старых проектах и в документации к некоторым API (например, к старой версии Google Maps API). Я не совсем понимаю, как это работает. Вроде бы, это способ обойти ограничения браузера на запросы к другому домену. Но как именно? И почему используется слово "padding" в названии? Допустим, у меня есть такой код на JavaScript, который пытается получить данные с другого сервера: ```javascript // Обычный fetch запрос к другому домену fetch('https://api.example.com/data') .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Ошибка:', error)); ``` Этот код не сработает, если сервер `api.example.com` не настроит CORS-заголовки. Но я слышал, что JSONP позволяет обойти это ограничение без поддержки CORS на сервере. Как такое возможно? Ведь браузер блокирует запросы — это же политика одного источника (Same-Origin Policy). Пожалуйста, объясните на пальцах: что такое JSONP, как он работает под капотом, и почему сейчас его считают устаревшим? Приведите простой пример, чтобы я мог понять механизм. <<>>

Что такое JSONP и как он работает

JSONP (JSON with Padding) — это старый, но хитрый способ получения данных с другого домена, который не требует настройки CORS. Он был придуман в 2005 году (задолго до появления CORS) и основан на простом наблюдении: браузер не блокирует загрузку <script> тегов с других доменов.

Вся суть JSONP заключается в том, что вы не делаете обычный AJAX-запрос (через fetch или XMLHttpRequest), а динамически создаёте <script> тег, который загружает JavaScript-файл с сервера. Этот файл — не просто JSON, а вызов функции с данными внутри. "Padding" (прокладка) — это как раз имя этой функции, которую сервер "оборачивает" вокруг JSON-данных.

Пример работы JSONP

Предположим, ваш сайт (mysite.com) хочет получить данные с api.example.com. Сервер должен поддерживать JSONP и принимать параметр callback.

Клиентская часть (ваш JavaScript):

// 1. Определяем функцию, которая будет вызвана, когда данные придут
function handleData(data) {
    console.log('Полученные данные:', data);
    // Здесь можно обновить интерфейс, отрисовать данные и т.д.
}

// 2. Создаем скрипт-тег динамически
function makeJsonpRequest(url) {
    const script = document.createElement('script');
    // Добавляем параметр callback с именем нашей функции
    script.src = url + '?callback=handleData';
    document.body.appendChild(script);
    // После загрузки скрипт автоматически выполнится
    // и вызовет handleData()
}

// 3. Выполняем запрос
makeJsonpRequest('https://api.example.com/data');

Серверная часть (пример на Node.js):

// Сервер получает запрос с ?callback=handleData
// Вместо обычного JSON он возвращает JavaScript:
// handleData({ "name": "Alice", "age": 30 });

app.get('/data', (req, res) => {
    const callbackName = req.query.callback; // 'handleData'
    const data = { name: "Alice", age: 30 };
    
    // Ключевой момент: оборачиваем JSON в вызов функции
    res.set('Content-Type', 'application/javascript');
    res.send(`${callbackName}(${JSON.stringify(data)})`);
});

Когда браузер загружает этот скрипт, он выполняет его как обычный JavaScript. В результате вызывается функция handleData с переданными данными. Браузер не блокирует этот процесс, потому что тег <script> не подпадает под Same-Origin Policy.

Почему JSONP сейчас считается устаревшим?

  • Безопасность: JSONP очень опасен. Вы доверяете стороннему серверу выполнить ЛЮБОЙ код на вашей странице. Если сервер взломан или недобросовестен, он может украсть данные пользователя (CSRF-атаки, XSS).
  • Только GET-запросы: JSONP работает исключительно через GET. Нельзя отправить POST, PUT или DELETE запрос.
  • Нет обработки ошибок: Вы не можете узнать, что пошло не так (404, 500, таймаут). Скрипт просто не выполнится.
  • Современная альтернатива — CORS: Начиная с 2010-х годов, все современные браузеры поддерживают CORS (Cross-Origin Resource Sharing). Это безопасный и гибкий механизм, который позволяет серверу явно разрешать запросы с определённых доменов.

Итог: JSONP — это исторический костыль, который использовали, когда CORS ещё не существовало. Если вы встретите его в старом коде — знайте, что его нужно заменять на современные fetch с CORS или, в крайнем случае, на прокси-сервер. Никогда не используйте JSONP в новых проектах!

<<>>

Альтернативный взгляд: как JSONP связан с iframe и window.name

JSONP — не единственный способ обойти Same-Origin Policy до эпохи CORS. Существовали и другие "хакерские" методы, например, использование iframe с обменом через window.name или location.hash. Однако JSONP стал самым популярным, потому что он был простым и работал напрямую с данными.

Ещё один важный момент: JSONP часто путают с JSON. Запомните разницу:

  • JSON — это формат данных: {"key": "value"}.
  • JSONP — это паттерн запроса, при котором сервер возвращает JavaScript-код: callback({"key": "value"}).

Если вы поддерживаете старое API и вынуждены использовать JSONP, обязательно проверяйте имя callback-функции на стороне сервера, чтобы злоумышленник не передал вредоносный код (например, alert('xss')). Лучше всего ограничить callback строгим регулярным выражением (только латинские буквы, цифры и подчёркивание).

На сегодняшний день JSONP можно встретить только в очень старых API (например, Yahoo Finance до 2017 года) или в некоторых публичных сервисах, которые не обновлялись. Любой современный API обязан поддерживать CORS. Если вы разработчик — используйте fetch с правильными заголовками Access-Control-Allow-Origin.