TL; DR
JSONP è un vecchio trucco inventato per aggirare la limitazione di sicurezza che ci proibisce di ottenere dati JSON da un server diverso (un'origine diversa * ).
Il trucco funziona usando un <script>
tag che richiede il JSON da quel luogo, ad es .: { "user":"Smith" }
, ma racchiuso in una funzione, il JSONP attuale ("JSON con Padding"):
peopleDataJSONP({"user":"Smith"})
La ricezione in questo modulo ci consente di utilizzare i dati all'interno della nostra peopleDataJSONP
funzione. JSONP è una cattiva pratica , non usarlo (leggi sotto)
Il problema
Supponiamo che stiamo navigando ourweb.com
e che vogliamo ottenere dati JSON (o qualsiasi dato non elaborato) da anotherweb.com
. Se dovessimo usare la richiesta GET (come XMLHttpRequest
, una fetch
chiamata, $.ajax
ecc.), Il nostro browser ci direbbe che non è permesso con questo brutto errore:
Come ottenere i dati desiderati? Bene, i <script>
tag non sono soggetti a questa limitazione dell'intero server (origine *)! Ecco perché possiamo caricare una libreria come jQuery o Google Maps da qualsiasi server, come un CDN, senza errori.
Punto importante : se ci pensate, quelle librerie sono reali, codice JS eseguibile (di solito una funzione enorme con tutta la logica all'interno). Ma dati grezzi? I dati JSON non sono codici . Non c'è niente da correre; sono solo dati semplici.
Pertanto, non c'è modo di gestire o manipolare i nostri preziosi dati. Il browser scaricherà i dati indicati dal nostro <script>
tag e durante l'elaborazione si lamenterà giustamente:
wtf è questa {"user":"Smith"}
merda che abbiamo caricato? Non è un codice. Non riesco a calcolare, errore di sintassi!
L'hack JSONP
Il vecchio / confuso modo di utilizzare quei dati? Abbiamo bisogno che quel server lo invii con un po 'di logica, quindi quando viene caricato, il tuo codice nel browser sarà in grado di utilizzare tali dati. Quindi il server esterno ci invia i dati JSON all'interno di una funzione JS. I dati stessi sono impostati come input di quella funzione. Sembra così:
peopleDataJSONP({"user":"Smith"})
che lo rende codice JS il nostro browser analizzerà senza lamentarsi! Esattamente come fa con la libreria jQuery. Ora, per ottenerlo in questo modo, il client "chiede" al server compatibile con JSONP, di solito fatto in questo modo:
<script src="https://anotherweb.com/api/data-from-people.json?myCallback=peopleDataJSONP"></script>
Il nostro browser riceverà JSONP con quel nome di funzione, quindi abbiamo bisogno di una funzione con lo stesso nome nel nostro codice, in questo modo:
const peopleDataJSONP = function(data){
alert(data.user); // "Smith"
}
O come questo, stesso risultato:
function peopleDataJSONP(data){
alert(data.user); // "Smith"
}
Il browser scaricherà il JSONP ed eseguirà, che chiama la nostra funzione , dove l'argomento data
sarà il nostro JSONP. Ora possiamo fare con i nostri dati qualunque cosa vogliamo.
Non utilizzare JSONP, utilizzare CORS
JSONP è un hack cross-site con alcuni aspetti negativi:
- Siamo in grado di eseguire solo richieste GET
- Poiché si tratta di una richiesta GET attivata da un semplice tag di script, non otteniamo errori utili o informazioni sullo stato di avanzamento
- Ci sono anche alcuni problemi di sicurezza, come l'esecuzione nel codice JS del client che potrebbe essere modificato in un payload dannoso
- Risolve solo il problema con i dati JSON, ma la politica di sicurezza Same-Origin si applica ad altri dati (Font Web, immagini / video disegnati con drawImage () ...)
- Non è molto elegante né leggibile.
L'asporto è che non è necessario usarlo al giorno d'oggi .
JSONP è il trucco per ottenere dati JSON da un altro server, ma violeremo lo stesso principio di sicurezza (Same-Origin) se avremo bisogno di altri tipi di cose tra siti.
Dovresti leggere qui su CORS , ma l'essenza è:
Cross-Origin Resource Sharing (CORS) è un meccanismo che utilizza intestazioni HTTP aggiuntive per indicare ai browser di fornire a un'applicazione Web in esecuzione su un'origine, l'accesso a risorse selezionate da un'origine diversa. Un'applicazione Web esegue una richiesta HTTP tra origini quando richiede una risorsa che ha un'origine diversa (dominio, protocollo o porta) dalla propria.
* l'origine è definita da 3 cose: protocollo , porta e host . Quindi, ad esempio, ha https://web.com
un'origine diversa rispetto a http://web.com
(protocollo diverso) e https://web.com:8081
(porta diversa) e ovviamente https://thatotherweb.net
(host diverso)