it-swarm-tr.com

JSONP nedir ve neden oluşturuldu?

JSON'u anlıyorum ama JSONP'yi değil. Wikipedia'nın JSON belgesinde , JSONP için en çok aranan sonuç oldu. Bu diyor ki:

JSONP veya "Dolgulu JSON" bir önek çağrısının kendisinin giriş argümanı olarak belirtildiği bir JSON uzantısıdır.

Ha? Ne çağrısı? Bu bana hiç mantıklı gelmiyor. JSON bir veri formatıdır. Arama yok.

2. arama sonucu , Remy isimli JSONP hakkında yazan bir adamdan geliyor:

JSONP yanıtı sunucudan kullanıcı tarafından belirlenen bir işleve ileten komut dosyası etiketi enjeksiyonudur.

Bunu anlayabilirim, ama hala bir anlam ifade etmiyor.


Peki JSONP nedir? Neden yaratıldı (hangi problemi çözüyor)? Ve neden kullanayım ki?


Ek : Az önce JSONP için yeni bir sayfa oluşturdum / Wikipedia'da; şimdi jvenema 'ın cevabını temel alan JSONP’ın net ve ayrıntılı bir açıklamasını içerir.

1955
Cheeso

Aslında çok da karmaşık değil.

Example.com etki alanında olduğunu ve domain example.net için bir istek yapmak istediğinizi varsayalım. Bunu yapmak için, tarayıcı alanlarının çoğunda bir hayır-hayır olan etki alanı sınırlarını geçmeniz gerekir.

Bu sınırlamayı atlayan öğe <script> etiketleridir. Bir komut dosyası etiketi kullandığınızda, etki alanı sınırlaması yoksayılır, ancak normal koşullar altında, sonuçlarla gerçekten do hiçbir şey yapamazsınız, komut dosyası yalnızca değerlendirilir.

JSONP'yi girin. İsteğinizi JSONP'nin etkin olduğu bir sunucuya yaptığınızda, sunucuya sayfanız hakkında biraz bilgi veren özel bir parametre iletirsiniz. Bu şekilde, sunucu yanıtını sayfanızın idare edebileceği şekilde güzel bir şekilde sarabilir.

Örneğin, sunucunun JSONP özelliklerini etkinleştirmek için "geri arama" adlı bir parametre beklediğini söyleyin. Sonra isteğiniz şöyle görünür:

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

JSONP olmadan, bunun gibi bazı temel JavaScript nesnelerini döndürebilir:

{ foo: 'bar' }

Bununla birlikte, JSONP ile sunucu "geri arama" parametresini aldığında, sonucu biraz farklı bir şekilde sarar ve şöyle bir şey döndürür:

mycallback({ foo: 'bar' });

Gördüğünüz gibi, şimdi belirttiğiniz yöntemi çağıracak. Böylece, sayfanızda geri arama işlevini tanımlarsınız:

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

Ve şimdi, komut dosyası yüklendiğinde, değerlendirilecek ve işleviniz yerine getirilecektir. Voila, etki alanları arası istekleri!

JSONP ile ilgili en büyük sorunu dikkat etmenizde yarar var: İsteğin kontrolünü çok kaybedersiniz. Örneğin, uygun arıza kodlarını geri almanın "Güzel" bir yolu yoktur. Sonuç olarak, isteği izlemek için zamanlayıcıları kullanırsınız, bu her zaman biraz şüphelidir. JSONRequest için teklif, etki alanları arası komut dosyası çalıştırmaya izin vermek, güvenliği sağlamak ve isteğin uygun şekilde kontrol edilmesini sağlamak için mükemmel bir çözümdür.

Bugünlerde (2015), CORS , JSONRequest'e göre önerilen bir yaklaşımdır. JSONP, daha eski tarayıcı desteği için kullanışlıdır, ancak CORS daha iyi bir seçenek olmadığı sürece, güvenlik açısından verilen sonuçlara göre.

1903
jvenema

JSONP, XMLHttpRequest aynı etki alanı politikasını yenmek için gerçekten basit bir püf noktasıdır. (Bildiğiniz gibi, biri farklı bir alana AJAX (XMLHttpRequest) isteği gönderemez.)

Öyleyse - XMLHttpRequest kullanmak yerine script HTML etiketlerini kullanmalıyız, js 'nin başka bir alandan veri alabilmesi için genellikle js dosyalarını yüklemek için kullandıklarınızı kullanın. Kulağa garip geliyor?

Şey: çıkıyor - script etiketleri XMLHttpRequest 'a benzeyen bir şekilde kullanılabilir! Şuna bir bak:

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

Verileri yükledikten sonra şuna benzeyen bir script segmenti ile sonuçlanacak:

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

Ancak bu biraz sakıncalıdır, çünkü bu diziyi script etiketinden almamız gerekiyor. Böylece JSONP yaratıcıları bunun daha iyi çalışacağına karar verdi (ve öyle):

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

Buradaki my_callback işlevine dikkat edin? Öyleyse - JSONP sunucusu isteğinizi aldığında ve geri arama parametresini bulduğunda - düz js dizisini döndürmek yerine şunu döndürür:

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

Kârın nerede olduğunu görün: şimdi verileri aldıktan sonra tetiklenecek olan otomatik geri çağırma (my_callback) alıyoruz.
JSONP hakkında bilmeniz gereken tek şey bu bir geri çağırma ve komut dosyası etiketleri.

NOT: bunlar JSONP kullanımının basit örnekleridir, bunlar üretime hazır komut dosyaları değildir.

Temel JavaScript örneği (JSONP kullanarak basit Twitter yayını)

<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>

Temel jQuery örneği (JSONP kullanarak basit Twitter beslemesi)

<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>


JSONPDolgu ile JSON anlamına gelir. (çok zayıf olarak adlandırılan teknik, çoğu insanın “doldurma” olarak düşünecekleri ile hiçbir ilgisi olmadığı için gerçekten.

674
ThatGuy

JSONP, uzak bir veri hizmeti konumu isteyen bir “komut dosyası” öğesi (HTML işaretlemesinde veya DOM içine JavaScript aracılığıyla eklenmiş) oluşturarak çalışır. Yanıt, tarayıcınıza önceden tanımlanmış işlevin adıyla birlikte gönderilen ve JSON verileri istenen parametre iletilen bir javascript. Betik çalıştırıldığında, işlev, talep eden sayfanın verileri almasına ve işlemesine izin vererek JSON verileriyle birlikte çağrılır.

Daha Fazla Okuma Ziyareti İçin: https://blogs.sap.com/2013/07/15/secret-behind-jsonp/

müşteri tarafında kod snippet'i

    <!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>

Sunucu tarafı PHP code

<?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 . ")";
?>
43
Ajain Vivek

Çünkü sunucudan dönen JSON nesnesine bir ön ek eklemesini isteyebilirsiniz. Örneğin

function_prefix(json_object);

tarayıcının eval olması için JSON dizesini bir ifade olarak "satır içi" olarak ayarlayın. Bu numara, sunucunun javascript kodunu doğrudan İstemci tarayıcısında "enjekte etmesini" ve "aynı Köken" kısıtlamalarını atlayarak bunu mümkün kılar.

Başka bir deyişle, etki alanları arası veri alışverişine sahip olabilirsiniz.


Normal olarak, XMLHttpRequest, etki alanları arası veri alışverişine doğrudan izin vermez (birinin aynı etki alanındaki bir sunucudan geçmesi gerekir);

<script src="some_other_domain/some_data.js&prefix=function_prefix> `one, Origin'den farklı bir alan adından verilere erişebilir.


Ayrıca kayda değer: Bu tür bir "hile" denemeden önce sunucu "güvenilir" olarak kabul edilmekle birlikte, nesne biçiminde vb. Olası değişikliklerin yan etkileri bulunabilir. JSON nesnesini almak için bir function_prefix (yani uygun bir js işlevi) kullanılırsa, söz konusu işlev döndürülen verileri kabul etmeden/işlemden önce kontroller yapabilir.

38
jldupont

JSONP, etki alanları arası komut dosyası oluşturma hatalarını gidermek için harika bir yerdir. Sunucu tarafında bir AJAX proxy'si uygulamak zorunda kalmadan, bir JSONP hizmetini yalnızca JS ile kullanabilirsiniz.

Nasıl çalıştığını görmek için b1t.co servisini kullanabilirsiniz. Bu, URL’lerinizi küçültmeniz için sizi yönlendiren ücretsiz bir JSONP hizmetidir. Hizmet için kullanılacak URL:

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

Örneğin, http://b1t.co/Site/api/External/MakeUrlWithGet?callback=whateverJavascriptName&url=google.com araması

dönecekti

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

Ve bu, js'nize bir src olarak yüklendiğinde, geri çağırma işleviniz olarak uygulamanız gereken her bir JavascriptAdı otomatik olarak çalışacaktır:

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

JSONP çağrısını gerçekten yapmak için birkaç yolla (jQuery kullanımı dahil) yapabilirsiniz ancak işte size saf bir JS örneği:

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);
}

Bir adım adım örnek ve üzerinde çalışmak için bir jsonp web servisi mevcuttur: bu yazı

18
dardawk

JSONP kullanımı için basit bir örnek.

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;

    ?>    
12
sarath joseph

JSONP'yi anlamadan önce, JSON biçimini ve XML'ini bilmeniz gerekir. Şu anda web'de en sık kullanılan veri formatı XML'dir, ancak XML oldukça karmaşıktır. Kullanıcıları Web sayfalarına gömülü işlem yapmak için elverişsiz kılar.

JavaScript'in veri alışverişi programı olarak bile kolayca veri alışverişi yapabilmesi için, JavaScript nesnelerine göre ifadeler kullanıyoruz ve JSON olan basit bir veri değişim formatı geliştirdik. JSON veri olarak veya bir JavaScript programı olarak kullanılabilir.

JSON doğrudan JavaScript'e eklenebilir, bunları kullanarak doğrudan belirli JSON programını çalıştırabilirsiniz, ancak güvenlik kısıtlamaları nedeniyle, tarayıcı Sandbox mekanizması etki alanları arası JSON kod çalıştırmasını devre dışı bırakır.

JSON'un yürütmeden sonra geçmesini sağlamak için bir JSONP geliştirdik. JSONP, tarayıcının güvenlik sınırlarını JavaScript Geri Arama işleviyle ve <script> etiketiyle atlar.

Kısacası JSONP'nin ne olduğunu, hangi sorunu çözdüğünü (ne zaman kullanacağını) açıklar.

10
Marcus Thornton

Harika cevaplar çoktan verildi, sadece parçamı javascript'te kod blokları şeklinde vermem gerekiyor (ayrıca, Orjinler arası talepler için daha modern ve daha iyi bir çözüm içereceğim: HTTP Başlıkları olan CORS):

JSONP:

1.client_jsonp.js

$.ajax({
    url: "http://api_test_server.proudlygeek.c9.io/?callback=?",
    dataType: "jsonp",
    success: function(data) {
        console.log(data);    
    }
});​​​​​​​​​​​​​​​​​​

2.server_jsonp.js

var http = require("http"),
    url  = require("url");

var server = http.createServer(function(req, res) {

    var callback = url.parse(req.url, true).query.callback || "myCallback";
    console.log(url.parse(req.url, true).query.callback);

    var data = {
        'name': "Gianpiero",
        'last': "Fiorelli",
        'age': 37
    };

    data = callback + '(' + JSON.stringify(data) + ');';

    res.writeHead(200, {'Content-Type': 'application/json'});
    res.end(data);
});

server.listen(process.env.PORT, process.env.IP);

console.log('Server running at '  + process.env.PORT + ':' + process.env.IP);

CORS:

3.client_cors.js

$.ajax({
    url: "http://api_test_server.proudlygeek.c9.io/",
    success: function(data) {
        console.log(data);    
    }
});​

4.server_cors.js

var http = require("http"),
    url  = require("url");

var server = http.createServer(function(req, res) {
    console.log(req.headers);

    var data = {
        'name': "Gianpiero",
        'last': "Fiorelli",
        'age': 37
    };

    res.writeHead(200, {
        'Content-Type': 'application/json',
        'Access-Control-Allow-Origin': '*'
    });

    res.end(JSON.stringify(data));
});

server.listen(process.env.PORT, process.env.IP);

console.log('Server running at '  + process.env.PORT + ':' + process.env.IP);
3
Humoyun