Considere a seguinte situação: você está tentando obter alguns dados de uma API em seu site usando fetch () , mas acaba conseguindo com um erro.

Você abre o console e vê “Nenhum cabeçalho Access-Control-Allow-Origin está presente no recurso solicitado” ou “O Access-Control-Allow-Origin header tem um valor que não é igual à origem fornecida ”escrito em texto vermelho, indicando que sua solicitação foi bloqueada pela política CORS.

Solicitação bloqueada devido ao CORS

Parece familiar? Com mais de 10.000 perguntas postadas sob a tag cors no StackOverflow, é um dos problemas mais comuns que afetam os desenvolvedores de front-end e os desenvolvedores de back-end. Então, qual é exatamente a política CORS e por que enfrentamos esse erro com frequência?

O que é Compartilhamento de Recursos de Origem Cruzada (CORS)?

Curiosamente, este não é um erro como o retratamos, mas sim o comportamento esperado. Nossos navegadores aplicam a política de mesma origem , que restringe o compartilhamento de recursos entre origens diferentes. Compartilhamento de recursos de origem cruzada ou CORS , é o mecanismo pelo qual podemos superar essa barreira. Para entender o CORS, vamos primeiro entender a política de mesma origem e sua necessidade.

A política de mesma origem

Em termos simples, a política de mesma origem é a versão da web “não fale com estranhos” incorporada pelo navegador.

Todos os navegadores modernos disponíveis hoje seguem a política de mesma origem que restringe como as solicitações XMLHttpRequest e fetch de uma origem interagem com um recurso de outra origem. O que é uma origem, exatamente?

É a combinação de um esquema, domínio e porta. O esquema pode ser HTTP, HTTPS, FTP ou qualquer outro. Da mesma forma, a porta também pode ser qualquer número de porta válido. As solicitações de mesma origem são essencialmente aquelas cujo esquema, domínio e porta correspondem. Vejamos o seguinte exemplo.

Supondo que nossa origem seja http://localhost: 3000 , as solicitações podem ser categorizadas em solicitações da mesma origem ou de origem cruzada da seguinte maneira:

Origem Tipo de solicitação Razão
http://localhost: 3000/about Mesma origem O caminho “/sobre” não é considerado parte da origem
http://localhost: 3000/shop/product.html Mesma origem O caminho “/shop/product.html” não é considerado parte da origem
http://localhost: 5000 Origem cruzada Porta diferente (5000 em vez de 3000)
https://localhost: 3000 Origem cruzada Esquema diferente (HTTPS em vez de HTTP)
https://blog.logrocket.com Origem cruzada Esquema, domínio e porta diferentes

Esta é a razão pela qual seu front-end em execução em http://localhost: 3000 não pode faça chamadas de API para seu servidor executando http://localhost: 5000 ou qualquer outra porta quando você desenvolver aplicativos de página única (SPAs).

Além disso, solicitações da origem https://mywebsite.com até a origem https://api.mywebsite.com ainda são consideradas solicitações entre sites, embora sejam de segunda origem é um subdomínio.

Devido à política de mesma origem, o navegador impedirá automaticamente que respostas de solicitações de origem cruzada sejam compartilhadas com o cliente. Isso é ótimo por motivos de segurança! Mas nem todos os sites são maliciosos e existem vários cenários em que pode ser necessário buscar dados de diferentes origens, especialmente na era moderna de arquitetura de microsserviço em que aplicativos diferentes são hospedados em origens diferentes.

Esta é uma excelente transição para nos aprofundarmos no CORS e aprendermos como usá-lo para permitir solicitações de origem cruzada.

Permitindo solicitações entre sites com CORS

Estabelecemos que o navegador não permite o compartilhamento de recursos entre origens diferentes, mas existem inúmeros exemplos em que podemos fazer isso. Como? É aqui que o CORS entra em cena.

CORS é um protocolo baseado em cabeçalho HTTP que permite o compartilhamento de recursos entre origens diferentes. Junto com os cabeçalhos HTTP, o CORS também depende da solicitação de pré-voo do navegador usando o método OPTIONS para solicitações não simples. Mais sobre solicitações simples e de comprovação posteriormente neste artigo.

Como os cabeçalhos HTTP são o ponto crucial do mecanismo CORS, vejamos esses cabeçalhos e o que cada um deles significa.

Access-Control-Allow-Origin

O cabeçalho de resposta Access-Control-Allow-Origin é talvez o cabeçalho HTTP mais importante definido pelo mecanismo CORS. O valor deste cabeçalho consiste em origens que têm permissão para acessar os recursos. Se este cabeçalho não estiver presente nos cabeçalhos de resposta, significa que o CORS não foi configurado no servidor.

Se este cabeçalho estiver presente, seu valor é verificado em relação ao cabeçalho Origem dos cabeçalhos de solicitação. Se os valores corresponderem, a solicitação será concluída com êxito e os recursos serão compartilhados. Em caso de incompatibilidade, o navegador responderá com um erro CORS.

Para permitir que todas as origens acessem os recursos no caso de uma API pública, o cabeçalho Access-Control-Allow-Origin pode ser definido como * no servidor. Para restringir apenas origens particulares para acessar os recursos, o cabeçalho pode ser definido para o domínio completo da origem do cliente, como https://mywebsite.com .

Access-Control-Allow-Methods

O cabeçalho de resposta Access-Control-Allow-Methods é usado para especificar o método HTTP permitido ou uma lista de métodos HTTP como GET , POST e PUT ao qual o servidor pode responder.

Este cabeçalho está presente na resposta de solicitações pré-iluminadas. Se o método HTTP de sua solicitação não estiver presente nesta lista de métodos permitidos, isso resultará em um erro CORS. Isso é muito útil quando você deseja impedir que os usuários modifiquem os dados por meio de POST , PUT , PATCH ou DELETE solicitações.

Access-Control-Allow-Headers

O cabeçalho de resposta Access-Control-Allow-Headers indica a lista de cabeçalhos HTTP permitidos que sua solicitação pode ter. Para oferecer suporte a cabeçalhos personalizados, como x-auth-token , você pode configurar o CORS em seu servidor adequadamente.

Solicitações que consistem em outros cabeçalhos além dos permitidos resultarão em um erro CORS. Semelhante ao cabeçalho Access-Control-Allow-Methods , este cabeçalho é usado em resposta a solicitações pré-veiculadas.

Access-Control-Max-Age

Solicitações pré-veiculadas exigem que o navegador primeiro faça uma solicitação ao servidor usando o método HTTP OPTIONS Só depois disso o pedido principal pode ser feito se for considerado seguro. No entanto, fazer a chamada OPTIONS para cada solicitação pré-veiculada pode ser caro.

Para evitar isso, o servidor pode responder com o cabeçalho Access-Control-Max-Age , permitindo que o navegador armazene em cache o resultado de solicitações pré-veiculadas por um determinado período de tempo. O valor deste cabeçalho é a quantidade de tempo em termos de segundos delta.

De modo geral, esta é a sintaxe de como os cabeçalhos de resposta CORS se parecem:

 Access-Control-Allow-Origin:  | *
Métodos de permissão de controle de acesso:  | []
Access-Control-Allow-Headers: 
| [] Access-Control-Max-Age:

Solicitações simples vs. solicitações pré-veiculadas

As solicitações que não acionam um preflight CORS se enquadram na categoria de solicitações simples. No entanto, a solicitação deve satisfazer algumas condições somente depois de ser considerada uma solicitação simples. Essas condições são:

  1. O método HTTP da solicitação deve ser um destes: GET , POST ou HEAD
  2. Os cabeçalhos da solicitação devem consistir apenas em cabeçalhos CORS da lista segura, como Aceitar , Aceitar-Language , Content-Language e Content-Type além dos cabeçalhos definidos automaticamente pelo agente do usuário
  3. O cabeçalho Content-Type deve ter apenas um destes três valores: application/x-www-form-urlencoded , multipart/form-data ou text/plain
  4. Nenhum ouvinte de evento é registrado no objeto retornado pela propriedade XMLHttpRequest.upload se estiver usando XMLHttpRequest
  5. Nenhum objeto ReadableStream deve ser usado na solicitação

Ao não atender a qualquer uma dessas condições, a solicitação é considerada uma solicitação de pré-veiculação. Para tais solicitações, o navegador deve primeiro enviar uma solicitação usando o método OPTIONS para a origem diferente.

Isso é usado para verificar se a solicitação real é segura para enviar ao servidor. A aprovação ou rejeição da solicitação real depende dos cabeçalhos de resposta à solicitação pré-veiculada. Se houver uma incompatibilidade entre esses cabeçalhos de resposta e os cabeçalhos da solicitação principal, a solicitação não será feita.

Habilitando CORS

Vamos considerar nossa situação inicial em que enfrentamos o erro CORS. Existem várias maneiras de resolver esse problema, dependendo se temos acesso ao servidor no qual os recursos estão hospedados. Podemos restringi-lo a duas situações:

  1. Você tem acesso ao back-end ou conhece o desenvolvedor de back-end
  2. Você pode gerenciar apenas o front-end e não pode acessar o servidor de back-end

Se você tiver acesso ao back-end:

Como o CORS é apenas um mecanismo baseado em cabeçalho HTTP, você pode configurar o servidor para responder com cabeçalhos apropriados para permitir o compartilhamento de recursos em diferentes origens. Dê uma olhada nos cabeçalhos CORS que discutimos acima e defina-os de acordo.

Para Node.js + desenvolvedores Express.js , você pode instalar o middleware cors do npm. Aqui está um snippet que usa a estrutura da web Express, juntamente com o middleware CORS:

 const express=require ('express');
const cors=require ('cors');
const app=express (); app.use (cors ()); app.get ('/', (req, res)=> { res.send ('API rodando com CORS habilitado');
}); app.listen (5000, console.log ('Servidor rodando na porta 5000'));

Se você não passar um objeto que consiste na configuração CORS, a configuração padrão será usada, que é equivalente a:

 { "origin":"*", "métodos":"GET, HEAD, PUT, PATCH, POST, DELETE", "preflightContinue": falso, "optionsSuccessStatus": 204
}

Veja como você pode configurar o CORS em seu servidor, que só permitirá solicitações GET de https://yourwebsite.com com cabeçalhos Content-Type e Authorization com um tempo de cache de comprovação de 10 minutos:

 app.use (cors ({ origem:'https://yourwebsite.com', métodos: ['GET'], allowedHeaders: ['Content-Type','Authorization'], maxAge: 600
}));

Embora este código seja específico para Express.js e Node.js, o conceito permanece o mesmo. Usando a linguagem de programação e a estrutura de sua escolha, você pode definir manualmente os cabeçalhos CORS com suas respostas ou criar um middleware personalizado para os mesmos.

Se você só tiver acesso ao frontend:

Muitas vezes, podemos não ter acesso ao servidor de back-end. Por exemplo, uma API pública. Devido a isso, não podemos adicionar cabeçalhos à resposta que recebemos. No entanto, podemos usar um servidor proxy que adicionará os cabeçalhos CORS à solicitação com proxy.

O projeto cors-anywhere é um Node.js proxy reverso que pode nos permitir fazer o mesmo. O servidor proxy está disponível em https://cors-anywhere.herokuapp.com/ , mas você pode construir seu próprio servidor proxy clonando o repositório e implantando-o em uma plataforma gratuita como Heroku ou qualquer outra plataforma desejada.

Neste método, em vez de fazer a solicitação diretamente ao servidor, desta forma:

 fetch ('https://jsonplaceholder.typicode.com/posts');

Basta anexar o URL do servidor proxy ao início do URL da API, assim:

 fetch ('https://cors-anywhere.herokuapp.com/https://jsonplaceholder.typicode.com/posts');

Conclusão

À medida que aprendemos a apreciar a política de mesma origem para sua segurança contra ataques de falsificação entre sites, o CORS parece fazer muito sentido. Embora as ocorrências das mensagens de erro CORS vermelhas no console não desapareçam por mágica, agora você está equipado com o conhecimento para lidar com essas mensagens, independentemente de trabalhar no front-end ou no back-end.

A postagem O guia definitivo para ativar o Compartilhamento de recursos de origem cruzada (CORS) apareceu primeiro no LogRocket Blog .