TL; DR
JSONP é um truque antigo inventado para contornar a restrição de segurança que nos proíbe obter dados JSON de um servidor diferente (uma origem diferente * ).
O truque funciona usando uma <script>
tag que solicita o JSON daquele local, por exemplo { "user":"Smith" }
:, mas envolvido em uma função, o JSONP real ("JSON with Padding"):
peopleDataJSONP({"user":"Smith"})
Recebê-lo desta forma nos permite usar os dados em nossa peopleDataJSONP
função. JSONP é uma prática ruim , não a use (leia abaixo)
O problema
Digamos que estamos navegando ourweb.com
e queremos obter dados JSON (ou quaisquer dados brutos) anotherweb.com
. Se usarmos a solicitação GET (como XMLHttpRequest
, umfetch
chamada, $.ajax
etc.), nosso navegador nos dirá que não é permitido com este erro feio:
Como obter os dados que queremos? Bem, as <script>
tags não estão sujeitas a toda essa restrição do servidor (origem *)! É por isso que podemos carregar uma biblioteca como o jQuery ou o Google Maps de qualquer servidor, como uma CDN, sem erros.
Ponto importante : se você pensar bem, essas bibliotecas são códigos JS reais e executáveis (geralmente uma função massiva com toda a lógica). Mas dados brutos? Dados JSON não são código . Não há nada para correr; são apenas dados simples.
Portanto, não há como manipular ou manipular nossos dados preciosos. O navegador fará o download dos dados apontados pela nossa <script>
tag e, ao processar, reclamará com razão:
wtf é essa {"user":"Smith"}
porcaria que carregamos? Não é código. Não consigo calcular, erro de sintaxe!
O corte JSONP
A maneira antiga / hacky de utilizar esses dados? Precisamos desse servidor para enviá-lo com alguma lógica, portanto, quando estiver carregado, seu código no navegador poderá usar esses dados. Portanto, o servidor estrangeiro nos envia os dados JSON dentro de uma função JS. Os dados em si são configurados como entrada dessa função. Se parece com isso:
peopleDataJSONP({"user":"Smith"})
o que torna o código JS que nosso navegador analisará sem reclamar! Exatamente como acontece com a biblioteca jQuery. Agora, para obtê-lo assim, o cliente "solicita" o servidor compatível com JSONP, geralmente feito assim:
<script src="https://anotherweb.com/api/data-from-people.json?myCallback=peopleDataJSONP"></script>
Nosso navegador receberá o JSONP com esse nome de função, portanto, precisamos de uma função com o mesmo nome em nosso código, assim:
const peopleDataJSONP = function(data){
alert(data.user); // "Smith"
}
Ou assim, o mesmo resultado:
function peopleDataJSONP(data){
alert(data.user); // "Smith"
}
O navegador fará o download do JSONP e o executará, que chama nossa função , onde o argumento data
será nosso JSON. Agora podemos fazer com nossos dados o que quisermos.
Não use JSONP, use CORS
JSONP é um hack entre sites com algumas desvantagens:
- Só podemos executar solicitações GET
- Como é uma solicitação GET acionada por uma simples tag de script, não obtemos erros úteis ou informações de progresso
- Existem também algumas preocupações de segurança, como a execução no código JS do cliente que pode ser alterado para uma carga maliciosa
- Ele resolve o problema apenas com dados JSON, mas a política de segurança Same-Origin se aplica a outros dados (WebFonts, imagens / vídeo desenhados com drawImage () ...)
- Não é muito elegante nem legível.
O argumento é que não há necessidade de usá-lo hoje em dia .
JSONP é o truque para obter dados JSON de outro servidor, mas violaremos o mesmo princípio de segurança (mesma origem) se precisarmos de outros tipos de coisas entre sites.
Você deve ler sobre o CORS aqui , mas a essência é:
O Compartilhamento de Recursos de Origem Cruzada (CORS) é um mecanismo que usa cabeçalhos HTTP adicionais para instruir os navegadores a fornecerem um aplicativo Web em execução em uma origem, acesso a recursos selecionados de uma origem diferente. Um aplicativo Web executa uma solicitação HTTP de origem cruzada quando solicita um recurso que tenha uma origem (domínio, protocolo ou porta) diferente da sua.
* origem é definida por três coisas: protocolo , porta e host . Então, por exemplo, https://web.com
é uma origem diferente de http://web.com
(protocolo diferente) e https://web.com:8081
(porta diferente) e obviamente https://thatotherweb.net
(host diferente)