TL; DR
JSONP es un viejo truco inventado para evitar la restricción de seguridad que nos prohíbe obtener datos JSON de un servidor diferente (un origen diferente * ).
El truco funciona mediante el uso de una <script>
etiqueta que solicita el JSON desde ese lugar, por ejemplo:, { "user":"Smith" }
pero envuelto en una función, el JSONP real ("JSON with Padding"):
peopleDataJSONP({"user":"Smith"})
Recibirlo de esta forma nos permite usar los datos dentro de nuestra peopleDataJSONP
función. JSONP es una mala práctica , no lo use (lea a continuación)
El problema
Digamos que estamos navegando ourweb.com
y queremos obtener datos JSON (o cualquier información en bruto realmente) anotherweb.com
. Si tuviéramos que usar la solicitud GET (como XMLHttpRequest
una fetch
llamada, $.ajax
etc.), nuestro navegador nos diría que no está permitido con este error feo:
¿Cómo obtener los datos que queremos? Bueno, ¡las <script>
etiquetas no están sujetas a toda esta restricción del servidor (origen *)! Es por eso que podemos cargar una biblioteca como jQuery o Google Maps desde cualquier servidor, como un CDN, sin ningún error.
Punto importante : si lo piensa, esas bibliotecas son códigos JS reales y ejecutables (generalmente una función masiva con toda la lógica dentro). ¿Pero datos en bruto? Los datos JSON no son código . No hay nada que correr; son solo datos simples.
Por lo tanto, no hay forma de manejar o manipular nuestros preciosos datos. El navegador descargará los datos señalados por nuestra <script>
etiqueta y, cuando lo procese, se quejará legítimamente:
wtf es esta {"user":"Smith"}
basura que cargamos? No es codigo. No puedo calcular, error de sintaxis!
El hack de JSONP
¿La forma antigua / hacky de utilizar esos datos? Necesitamos que ese servidor lo envíe con cierta lógica, por lo que cuando esté cargado, su código en el navegador podrá usar dichos datos. Entonces, el servidor externo nos envía los datos JSON dentro de una función JS. Los datos en sí se configuran como la entrada de esa función. Se parece a esto:
peopleDataJSONP({"user":"Smith"})
¡lo que lo convierte en código JS que nuestro navegador analizará sin quejarse! Exactamente como lo hace con la biblioteca jQuery. Ahora, para que sea así, el cliente "pregunta" al servidor compatible con JSONP, generalmente hecho así:
<script src="https://anotherweb.com/api/data-from-people.json?myCallback=peopleDataJSONP"></script>
Nuestro navegador recibirá el JSONP con ese nombre de función, por lo tanto, necesitamos una función con el mismo nombre en nuestro código, como esta:
const peopleDataJSONP = function(data){
alert(data.user); // "Smith"
}
O así, el mismo resultado:
function peopleDataJSONP(data){
alert(data.user); // "Smith"
}
El navegador descargará el JSONP y lo ejecutará, que llama a nuestra función , donde el argumento data
será nuestro JSON. Ahora podemos hacer con nuestros datos lo que queramos.
No uses JSONP, usa CORS
JSONP es un truco entre sitios con algunas desventajas:
- Solo podemos realizar solicitudes GET
- Como se trata de una solicitud GET activada por una etiqueta de script simple, no obtenemos errores útiles ni información de progreso
- También hay algunos problemas de seguridad, como ejecutar en el código JS de su cliente que podría cambiarse a una carga maliciosa
- Solo resuelve el problema con los datos JSON, pero la política de seguridad del mismo origen se aplica a otros datos (WebFonts, imágenes / video dibujados con drawImage () ...)
- No es muy elegante ni legible.
La conclusión es que no hay necesidad de usarlo hoy en día .
JSONP es el truco para obtener datos JSON de otro servidor, pero violaremos el mismo principio de seguridad (Same-Origin) si necesitamos otros tipos de cosas entre sitios.
Debería leer sobre CORS aquí , pero lo esencial es:
Cross-Origin Resource Sharing (CORS) es un mecanismo que utiliza encabezados HTTP adicionales para indicar a los navegadores que den a una aplicación web que se ejecuta en un origen, acceso a recursos seleccionados de un origen diferente. Una aplicación web ejecuta una solicitud HTTP de origen cruzado cuando solicita un recurso que tiene un origen (dominio, protocolo o puerto) diferente al suyo.
* El origen está definido por 3 cosas: protocolo , puerto y host . Entonces, por ejemplo, https://web.com
es un origen diferente que http://web.com
(protocolo diferente) y https://web.com:8081
(puerto diferente) y obviamente https://thatotherweb.net
(host diferente)