Artigo original escrito por: Shruti Kapoor
Artigo original: The Access-Control-Allow-Origin Header Explained – With a CORS Example
Traduzido e adaptado por: Daniel Rosa

Frequentemente, ao chamarmos uma API, vemos um erro no console com essa aparência:


Access to fetch at 'http://um_site_qualquer.com' from origin 'http://seu_site.com' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header has a value that is not equal to the supplied origin

Neste artigo, aprenderemos o motivo de esse erro aparecer e como resolvê-lo.

O que é o cabeçalho Access-Control-Allow-Origin?

Access-Control-Allow-Origin é um cabeçalho de CORS. CORS, ou Cross Origin Resource Sharing (em português, "compartilhamento de recursos de origens diferentes"), é um mecanismo que os navegadores têm para permitir que um site em execução no ponto de origem A solicite recursos no ponto de origem B.

"Origin", ou origem, neste caso, não é apenas um nome de host, mas uma combinação da porta, do nome do host e do esquema, por exemplo: http://meu_site.exemplo.com:8080/

Aqui temos um exemplo do que acontece -

  1. Tenho um ponto de origem A: http://meu_site.com e quero obter recursos do ponto de origem B: http://seu_site.com.
  2. Para proteger a sua segurança, o navegador não me permitirá acessar recursos de seu_site.com e bloqueará minha solicitação.
  3. Para permitir que o ponto de origem A acesse seus recursos, o ponto de origem B precisará permitir que o navegador saiba que não há problema em me permitir obter recursos de seu ponto de origem.

Aqui temos um exemplo da Mozilla Developer Network que explica bem o caso:

CORS_principle
https://developer.mozilla.org/pt-BR/docs/Web/HTTP/CORS

Com a ajuda do CORS, os navegadores permitem que os pontos de origem compartilhem recursos entre eles.

Existem alguns cabeçalhos (texto em inglês) que permitem o compartilhamento de recursos entre pontos de origem, mas o principal deles é Access-Control-Allow-Origin. Ele informa o navegador quais origens têm a permissão de receber solicitações nesse servidor.

Quem precisa definir Access-Control-Allow-Origin?

Para entender quem precisa definir esse cabeçalho, pense no seguinte cenário: você está navegando por um site da web que é usado para visualizar e ouvir música. O site tenta fazer uma conexão com seu banco em segundo plano de modo inadequado.

Quem deve ter, ao final de contas, a capacidade de evitar que esse site da web malicioso roube dados do banco? O banco! Assim, é o banco que precisará proteger seus recursos, definindo o cabeçalho Access-Control-Allow-Origin como parte da resposta.

Lembre-se: o ponto de origem responsável por servir os recursos é quem precisa definir esse cabeçalho.

Como usar e quando passar esse cabeçalho

Aqui temos um exemplo dos valores que você pode definir:

  1. Access-Control-Allow-Origin : *: permite qualquer origem.
  2. Access-Control-Allow-Origin : http://mysite.com: permite solicitações apenas de meu_site.com.

Vejamos isso em funcionamento

Vamos ver um exemplo. Você pode conferir esse código no meu repositório no GitHub.

Criaremos um servidor no ponto de origem A http://localhost:8000, que enviará a Hello a um endpoint da api. Chamaremos esse endpoint criando um client no ponto de origem B http://localhost:3000 e usaremos a api fetch para solicitar o recurso. Esperamos ver a string Hello ser passada pelo ponto de origem A ao console do navegador do ponto de origem B.

Vamos supor que nós temos um ponto de origem em funcionamento em http://localhost:8000 que serve esse recurso no endpoint /api. O servidor envia uma resposta com o cabeçalho Access-Control-Allow-Origin.

const express = require("express");

const app = express();
const port = process.env.SERVER_PORT || 8000;

// Adicionar os cabeçalhos Access-Control-Allow-Origin
app.use((req, res, next) => {
  res.setHeader("Access-Control-Allow-Origin", "https://seu_site.com");
  res.header(
    "Access-Control-Allow-Headers",
    "Origin, X-Requested-With, Content-Type, Accept"
  );
  next();
});

app.get("/api", (req, res) => {
  res.json("Hello");
});

app.listen(port, () => console.log(`Listening on port ${port}`));

No lado do client, você pode chamar esse endpoint através de fetch, assim:

fetch('http://localhost:8000/api')
.then(res => res.json())
.then(res => console.log(res));

Agora, abra o console do navegador para ver o resultado.
Como o cabeçalho, de momento, está definido para aceitar acessos apenas de https://seu_site.com, o navegador bloqueará o acesso ao recurso e você verá um erro no console.

CORS-access-denied

Agora, para consertarmos isso, altere os cabeçalhos para:

 res.setHeader("Access-Control-Allow-Origin", "*");

Confira o console do navegador e agora você verá a string Hello.

Quer saber mais sobre JS? Visite o site da autora.