JSONP: O que é, por que foi criado e por que o CORS o substituiu

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

JSONP: A arma secreta do frontend do passado

\n

Imagine que você é um desenvolvedor web em 2010. Você precisa obter dados de um servidor de terceiros, por exemplo, a previsão do tempo ou a cotação de moedas. Você escreve uma simples requisição fetch, mas no console do navegador aparece um erro vermelho: «No 'Access-Control-Allow-Origin' header is present». Familiar?

\n

Isso é a Same-Origin Policy (política de mesma origem) impedindo seu JavaScript de sair do domínio de origem. Mas como funcionavam os widgets de previsão do tempo, botões «Compartilhar» e contadores de visitas? A resposta é simples: eles usavam JSONP — um truque engenhoso sobre o qual vamos falar hoje.

\n

Neste artigo, responderemos à pergunta popular do Stack Overflow: «What is JSONP, and why was it created?» — em linguagem simples, com exemplos de código e sem teoria desnecessária.

\n\n

1. O problema: Por que o navegador bloqueia requisições?

\n

O navegador é paranóico. Ele protege o usuário contra ataques XSS e roubo de dados. A Same-Origin Policy permite que o JavaScript leia respostas apenas do mesmo domínio, protocolo e porta.

\n

Exemplo de bloqueio:

\n
// Este código causará um erro CORS\nfetch('https://api.distant-server.com/data')\n  .then(response => response.json())\n  .then(data => console.log(data));
\n

Mas há uma exceção: as tags <script>. O navegador carrega scripts de qualquer domínio sem problemas! É exatamente essa brecha que o JSONP utiliza.

\n\n

2. A solução: JSONP — JSON com Padding

\n

JSONP (JSON with Padding) não é uma tecnologia nem um formato de dados, mas sim um padrão (gambiarra) que contorna a Same-Origin Policy através da tag <script>.

\n

A ideia é simples: em vez de fazer uma requisição via XMLHttpRequest, criamos dinamicamente um elemento <script>, apontamos para a URL do servidor, e o servidor retorna não um JSON, mas um código JavaScript que chama nossa função com os dados.

\n\n

Como é um JSON comum:

\n
// Resposta do servidor (JSON comum)\n{"name": "PythonLib", "topic": "JSONP"}
\n\n

Como é um JSONP:

\n
// Resposta do servidor (JSONP)\nmyCallback({"name": "PythonLib", "topic": "JSONP"});
\n

A diferença é colossal: no segundo caso, o servidor envolve os dados em uma chamada de função myCallback. Esse é o tal padding (invólucro).

\n\n

3. Prática: Escrevendo uma requisição JSONP manualmente

\n

Vamos implementar um cliente JSONP em JavaScript puro. Isso ajudará a entender a mágica.

\n\n
function jsonp(url, callbackName) {\n  // 1. Cria uma função global (callback)\n  window[callbackName] = function(data) {\n    console.log('Dados recebidos:', data);\n    delete window[callbackName]; // Limpa a bagunça\n    document.body.removeChild(script);\n  };\n\n  // 2. Cria a tag script\n  const script = document.createElement('script');\n  script.src = `${url}?callback=${callbackName}`; // Passa o nome do callback\n  script.onerror = function() {\n    console.error('Erro ao carregar JSONP');\n    delete window[callbackName];\n    document.body.removeChild(script);\n  };\n\n  // 3. Adiciona ao DOM — o navegador carrega e executa o script imediatamente\n  document.body.appendChild(script);\n}\n\n// Usando:\njsonp('https://api.example.com/data', 'handleData');
\n

Como funciona passo a passo:

\n
    \n
  • Criamos uma função global handleData.
  • \n
  • Adicionamos a tag <script> com a URL do servidor. Na URL, passamos o parâmetro ?callback=handleData.
  • \n
  • O servidor que suporta JSONP vê o parâmetro callback e retorna não um JSON, mas um JavaScript: handleData({...}).
  • \n
  • O navegador executa esse script, nossa função é chamada e recebemos os dados.
  • \n
\n\n

4. Por que JSONP é o mal? (Desvantagens)

\n

Se você pensou: «Legal, vou usar em tudo

Blogs

Book Recommendations