Что такое JSONP?

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

JSONP или "JSON с дополнением" - это расширение JSON, в котором префикс указан как входной аргумент самого вызова.

А? Какой звонок? Это не имеет никакого смысла для меня. JSON - это формат данных. Нет вызова.

второй результат поиска от какого-то парня по имени Remy, который пишет об JSONP:

JSONP - это инъекция тега script, передающая ответ от сервера в указанную пользователем функцию.

Я могу понять это, но это все еще не имеет никакого смысла.


Итак, что такое JSONP? Почему он был создан (какая проблема его решает)? И зачем мне это использовать?


Добавление. Я только что создал новую страницу для JSONP в Википедии; теперь у него есть четкое и подробное описание JSONP на основе ответа jvenema.

1838
задан Cheeso 14 янв. '10 в 23:53
источник поделиться
7 ответов

Это на самом деле не слишком сложно...

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

Один элемент, который обходит это ограничение, - это теги <script>. Когда вы используете тег скрипта, ограничение домена игнорируется, но при нормальных обстоятельствах вы ничего не можете сделать с результатами, скрипт просто получает оценку.

Введите JSONP. Когда вы делаете свой запрос на сервер, который включен JSONP, вы передаете специальный параметр, который немного сообщает серверу о вашей странице. Таким образом, сервер может красиво завершать свой ответ так, как может обрабатывать ваша страница.

Например, скажем, сервер ожидает параметр "обратный вызов", чтобы включить его возможности JSONP. Тогда ваш запрос будет выглядеть так:

http://www.example.net/sample.aspx?callback=mycallback

Без JSONP это может вернуть некоторый базовый объект JavaScript, например:

{ foo: 'bar' }

Однако с JSONP, когда сервер получает параметр "обратный вызов", он немного уменьшает результат, возвращая что-то вроде этого:

mycallback({ foo: 'bar' });

Как вы можете видеть, теперь он будет вызывать указанный вами метод. Итак, на вашей странице вы определяете функцию обратного вызова:

mycallback = function(data){
  alert(data.foo);
};

И теперь, когда скрипт будет загружен, он будет оценен, и ваша функция будет выполнена. Voila, междоменные запросы!

Также стоит отметить одну серьезную проблему с JSONP: вы теряете много контроля над запросом. Например, нет "хорошего" способа вернуть коды отказа. В результате вы в конечном итоге используете таймеры для отслеживания запроса и т.д., Что всегда немного подозрительно. Предложение для JSONRequest - отличное решение для разрешения междоменного скриптинга, поддержания безопасности и обеспечения надлежащего контроля над запросом.

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

1801
ответ дан jvenema 15 янв. '10 в 0:08
источник поделиться

JSONP - действительно простой трюк для преодоления той же политики домена XMLHttpRequest. (Как вы знаете, нельзя отправить запрос AJAX (XMLHttpRequest) в другой домен.)

Итак - вместо использования XMLHttpRequest мы должны использовать теги HTML script, те, которые вы обычно используете для загрузки js файлов, чтобы js мог получать данные из другого домена. Звучит странно?

Вещь - получается script теги могут использоваться по типу, подобному XMLHttpRequest! Проверьте это:

script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'http://www.someWebApiServer.com/some-data';

В итоге вы получите сегмент script, который выглядит следующим образом после загрузки данных:

<script>
{['some string 1', 'some data', 'whatever data']}
</script>

Однако это немного неудобно, потому что мы должны получить этот массив из тега script. Поэтому создатели JSONP решили, что это будет работать лучше (и это так):

script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'http://www.someWebApiServer.com/some-data?callback=my_callback';

Обратите внимание на функцию my_callback. Итак - когда сервер JSONP получает ваш запрос и находит параметр обратного вызова - вместо возврата простого массива js он возвращает это:

my_callback({['some string 1', 'some data', 'whatever data']});

Посмотрите, где прибыль: теперь мы получаем автоматический обратный вызов (my_callback), который будет запущен после получения данных.
Это все, что нужно знать о JSONP: это обратный вызов и теги script.

ПРИМЕЧАНИЕ. Это простые примеры использования 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 type="text/javascript" src="http://twitter.com/status/user_timeline/padraicb.json?count=10&callback=myCallback"></script>
    </body>
</html>

Основной пример jQuery (простой канал Twitter с использованием JSONP)

<html>
    <head>
        <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
        <script>
            $(document).ready(function(){
                $.ajax({
                    url: 'http://twitter.com/status/user_timeline/padraicb.json?count=10',
                    dataType: 'jsonp',
                    success: function(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>'
                        }
                        $('#twitterFeed').html(text);
                    }
                });
            })
        </script>
    </head>
    <body>
        <div id = 'twitterFeed'></div>
    </body>
</html>


JSONP означает JSON с Padding. (очень плохо названная техника, так как она действительно не имеет ничего общего с тем, что большинство людей будет воспринимать как "заполнение".)

643
ответ дан ThatGuy 30 июля '11 в 0:40
источник поделиться

JSONP работает, создавая элемент "script" (либо в разметке HTML, либо вставляется в DOM через JavaScript), который запрашивает местоположение удаленной службы данных. Ответ - это javascript, загруженный в ваш браузер с именем предопределенной функции вместе с передаваемым параметром, который запрашивает данные JSON. Когда выполняется script, функция вызывается вместе с данными JSON, позволяя запрашивающей странице получать и обрабатывать данные.

Для дальнейшего чтения: https://blogs.sap.com/2013/07/15/secret-behind-jsonp/

фрагмент кода на стороне клиента

    <!DOCTYPE html>
    <html lang="en">
    <head>
     <title>AvLabz - CORS : The Secrets Behind JSONP </title>
     <meta charset="UTF-8" />
    </head>
    <body>
      <input type="text" id="username" placeholder="Enter Your Name"/>
      <button type="submit" onclick="sendRequest()"> Send Request to Server </button>
    <script>
    "use strict";
    //Construct the script tag at Runtime
    function requestServerCall(url) {
      var head = document.head;
      var script = document.createElement("script");

      script.setAttribute("src", url);
      head.appendChild(script);
      head.removeChild(script);
    }

    //Predefined callback function    
    function jsonpCallback(data) {
      alert(data.message); // Response data from the server
    }

    //Reference to the input field
    var username = document.getElementById("username");

    //Send Request to Server
    function sendRequest() {
      // Edit with your Web Service URL
      requestServerCall("http://localhost/PHP_Series/CORS/myService.php?callback=jsonpCallback&message="+username.value+"");
    }    

  </script>
   </body>
   </html>

Часть кода сервера PHP-кода

<?php
    header("Content-Type: application/javascript");
    $callback = $_GET["callback"];
    $message = $_GET["message"]." you got a response from server yipeee!!!";
    $jsonResponse = "{\"message\":\"" . $message . "\"}";
    echo $callback . "(" . $jsonResponse . ")";
?>
38
ответ дан Ajain Vivek 17 марта '13 в 16:32
источник поделиться

Потому что вы можете попросить сервер добавить префикс к возвращенному объекту JSON. Например

function_prefix(json_object);

чтобы браузер eval "встроил" строку JSON в качестве выражения. Этот трюк позволяет серверу "вводить" javascript-код непосредственно в браузере клиента, и это обходит ограничения "того же происхождения".

Другими словами, вы можете иметь обмен данными между доменами.


Обычно XMLHttpRequest не разрешает междоменный обмен данными напрямую (нужно пройти через сервер в том же домене), тогда как:

<script src="some_other_domain/some_data.js&prefix=function_prefix > `можно получить доступ к данным из домена, отличного от исходного.


Также стоит отметить: несмотря на то, что сервер должен считаться "доверенным" перед попыткой такого "трюка", могут содержаться побочные эффекты возможных изменений в формате объекта и т.д. Если для приема объекта JSON используется function_prefix (т.е. Собственная функция js), эта функция может выполнять проверки перед принятием/дальнейшей обработкой возвращенных данных.

37
ответ дан jldupont 14 янв. '10 в 23:58
источник поделиться

JSONP отлично справляется с ошибками междоменного скриптинга. Вы можете использовать сервис JSONP исключительно с помощью JS без необходимости использования прокси-сервера AJAX на стороне сервера.

Вы можете использовать службу b1t.co, чтобы увидеть, как она работает. Это бесплатный сервис JSONP, который позволяет вам минимизировать ваши URL-адреса. Вот URL-адрес для использования:

http://b1t.co/Site/api/External/MakeUrlWithGet?callback=[resultsCallBack]&url=[escapedUrlToMinify]

Например, вызов http://b1t.co/Site/api/External/MakeUrlWithGet?callback=whateverJavascriptName&url=google.com

вернет

whateverJavascriptName({"success":true,"url":"http://google.com","shortUrl":"http://b1t.co/54"});

И, таким образом, когда это загрузится в js как src, оно автоматически запустит anyJavascriptName, которое вы должны реализовать в качестве функции обратного вызова:

function minifyResultsCallBack(data)
{
    document.getElementById("results").innerHTML = JSON.stringify(data);
}

Чтобы сделать JSONP-вызов, вы можете сделать это несколькими способами (в том числе с использованием jQuery), но вот пример JSON:

function minify(urlToMinify)
{
   url = escape(urlToMinify);
   var s = document.createElement('script');
   s.id = 'dynScript';
   s.type='text/javascript';
   s.src = "http://b1t.co/Site/api/External/MakeUrlWithGet?callback=resultsCallBack&url=" + url;
   document.getElementsByTagName('head')[0].appendChild(s);
}

Пошаговый пример и веб-сервис jsonp для практики доступны по адресу: этот пост

17
ответ дан dardawk 28 марта '13 в 18:59
источник поделиться

Простой пример использования JSONP.

client.html

    <html>
    <head>
   </head>
     body>


    <input type="button" id="001" onclick=gO("getCompany") value="Company"  />
    <input type="button" id="002" onclick=gO("getPosition") value="Position"/>
    <h3>
    <div id="101">

    </div>
    </h3>

    <script type="text/javascript">

    var elem=document.getElementById("101");

    function gO(callback){

    script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = 'http://localhost/test/server.php?callback='+callback;
    elem.appendChild(script);
    elem.removeChild(script);


    }

    function getCompany(data){

    var message="The company you work for is "+data.company +"<img src='"+data.image+"'/   >";
    elem.innerHTML=message;
}

    function getPosition(data){
    var message="The position you are offered is "+data.position;
    elem.innerHTML=message;
    }
    </script>
    </body>
    </html>

server.php

  <?php

    $callback=$_GET["callback"];
    echo $callback;

    if($callback=='getCompany')
    $response="({\"company\":\"Google\",\"image\":\"xyz.jpg\"})";

    else
    $response="({\"position\":\"Development Intern\"})";
    echo $response;

    ?>    
10
ответ дан sarath joseph 06 июня '14 в 9:45
источник поделиться

Прежде чем понимать JSONP, вам необходимо знать формат JSON и XML. В настоящее время наиболее часто используемым форматом данных в Интернете является XML, но XML очень сложный. Это делает пользователей неудобными для обработки встроенных веб-страниц.

Чтобы JavaScript мог легко обмениваться данными, даже как программа обработки данных, мы используем формулировку в соответствии с объектами JavaScript и разработали простой формат обмена данными, который является JSON. JSON может использоваться как данные или как программа JavaScript.

JSON может быть непосредственно встроен в JavaScript, используя их, вы можете напрямую выполнять определенную программу JSON, но из-за ограничений безопасности механизм Sandbox браузера отключает выполнение кода JSON междоменного доступа.

Чтобы JSON мог быть передан после выполнения, мы разработали JSONP. JSONP обходит ограничения безопасности браузера с помощью функции обратного вызова JavaScript и <script> .

Итак, кратко объясняет, что такое JSONP, какую проблему он решает (когда его использовать).

9
ответ дан Marcus Thornton 08 дек. '15 в 7:02
источник поделиться

Другие вопросы по меткам