Esta resposta cobre muito terreno, por isso é dividida em três partes:
- Como usar um proxy CORS dar a volta “No Access-Control-Allow-Origin cabeçalho” problemas
- Como evitar o preflight do CORS
- Como corrigir os problemas do cabeçalho "Acesso-controle-permissão-origem" não deve ser o curinga
Como usar um proxy CORS dar a volta “No Access-Control-Allow-Origin cabeçalho” problemas
Se você não controlar o servidor, seu código JavaScript de front-end está enviando uma solicitação e o problema com a resposta desse servidor é apenas a falta do Access-Control-Allow-Origincabeçalho necessário , você ainda poderá fazer as coisas funcionarem - fazendo a solicitação por meio de um Proxy CORS. Para mostrar como isso funciona, primeiro, aqui está um código que não usa um proxy CORS:
const url = "https://example.com"; // site that doesn’t send Access-Control-*
fetch(url)
.then(response => response.text())
.then(contents => console.log(contents))
.catch(() => console.log("Can’t access " + url + " response. Blocked by browser?"))
O motivo pelo qual o catchbloco é atingido é que o navegador impede que esse código acesse a resposta da qual ele volta https://example.com. E a razão pela qual o navegador faz isso é que a resposta não possui o Access-Control-Allow-Origincabeçalho de resposta.
Agora, aqui está exatamente o mesmo exemplo, mas apenas com um proxy CORS adicionado em:
const proxyurl = "https://cors-anywhere.herokuapp.com/";
const url = "https://example.com"; // site that doesn’t send Access-Control-*
fetch(proxyurl + url) // https://cors-anywhere.herokuapp.com/https://example.com
.then(response => response.text())
.then(contents => console.log(contents))
.catch(() => console.log("Can’t access " + url + " response. Blocked by browser?"))
Nota: Se https://cors-anywhere.herokuapp.com estiver inativo ou indisponível quando você o experimentar, veja abaixo como implantar seu próprio servidor CORS Anywhere no Heroku em apenas 2-3 minutos.
O segundo trecho de código acima pode acessar a resposta com êxito, porque pegar o URL da solicitação e alterá-lo para https://cors-anywhere.herokuapp.com/https://example.com - apenas prefixando-o com o URL do proxy - causa o solicitação a ser feita através desse proxy, que então:
- Encaminha a solicitação para
https://example.com.
- Recebe a resposta de
https://example.com.
- Adiciona o
Access-Control-Allow-Origincabeçalho à resposta.
- Passa essa resposta, com esse cabeçalho adicionado, de volta ao código de front-end solicitante.
O navegador então permite que o código de front-end acesse a resposta, porque essa resposta com o Access-Control-Allow-Origincabeçalho da resposta é o que o navegador vê.
Você pode executar facilmente seu próprio proxy usando o código de https://github.com/Rob--W/cors-anywhere/ .
Você também pode implantar facilmente seu próprio proxy no Heroku em literalmente apenas 2-3 minutos, com 5 comandos:
git clone https://github.com/Rob--W/cors-anywhere.git
cd cors-anywhere/
npm install
heroku create
git push heroku master
Após a execução desses comandos, você terminará com seu próprio servidor CORS Anywhere em execução, por exemplo, em https://cryptic-headland-94862.herokuapp.com/ . Portanto, em vez de prefixar seu URL de solicitação https://cors-anywhere.herokuapp.com, prefixe-o com o URL da sua própria instância; por exemplo, https://cryptic-headland-94862.herokuapp.com/https://example.com .
Portanto, se você tentar usar https://cors-anywhere.herokuapp.com, descobrir que está em baixo (o que às vezes acontece), considere obter uma conta Heroku (se ainda não o fez) e faça 2 ou 3 minutos para executar as etapas acima para implantar seu próprio servidor CORS Anywhere no Heroku.
Independentemente de você executar ou usar https://cors-anywhere.herokuapp.com ou outro proxy aberto, esta solução funcionará mesmo se a solicitação for aquela que aciona os navegadores para fazer uma OPTIONSsolicitação de comprovação CORS - porque, nesse caso, o O proxy também envia de volta os cabeçalhos Access-Control-Allow-Headerse Access-Control-Allow-Methodsnecessários para tornar o preflight bem-sucedido.
Como evitar o preflight do CORS
O código na pergunta aciona um preflight do CORS, pois envia um Authorizationcabeçalho.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests
Mesmo sem isso, o Content-Type: application/jsoncabeçalho também acionaria o preflight.
O que “comprovar” significa: antes que o navegador tente digitar o POSTcódigo da pergunta, ele primeiro envia uma OPTIONSsolicitação ao servidor - para determinar se o servidor está optando por receber uma origem cruzada POSTque inclua os cabeçalhos Authorizatione Content-Type: application/json.
Funciona muito bem com um pequeno script curl - eu recebo meus dados.
Para testar corretamente curl, você deve emular a OPTIONSsolicitação de comprovação que o navegador envia:
curl -i -X OPTIONS -H "Origin: http://127.0.0.1:3000" \
-H 'Access-Control-Request-Method: POST' \
-H 'Access-Control-Request-Headers: Content-Type, Authorization' \
"https://the.sign_in.url"
... https://the.sign_in.urlsubstituído por qualquer que seja o seu sign_inURL real .
A resposta que o navegador precisa receber dessa OPTIONSsolicitação deve incluir cabeçalhos como este:
Access-Control-Allow-Origin: http://127.0.0.1:3000
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: Content-Type, Authorization
Se a OPTIONSresposta não incluir esses cabeçalhos, o navegador será interrompido e nunca tentará enviar a POSTsolicitação. Além disso, o código de status HTTP para a resposta deve ser 2xx - normalmente 200 ou 204. Se houver outro código de status, o navegador irá parar ali.
O servidor na pergunta está respondendo à OPTIONSsolicitação com um código de status 501, o que aparentemente significa que está tentando indicar que não implementa suporte para OPTIONSsolicitações. Outros servidores normalmente respondem com um código de status 405 "Método não permitido" neste caso.
Portanto, você nunca poderá fazer POSTsolicitações diretamente a esse servidor a partir do seu código JavaScript de front-end se o servidor responder a essa OPTIONSsolicitação com um 405 ou 501 ou qualquer coisa que não seja um 200 ou 204 ou se não responder com os necessários cabeçalhos de resposta.
A maneira de evitar o desencadeamento de um preflight para o caso na pergunta seria:
- se o servidor não exigir um
Authorizationcabeçalho de solicitação, mas (por exemplo) se basear nos dados de autenticação incorporados no corpo da POSTsolicitação ou como um parâmetro de consulta
- se o servidor não exigiu que o
POSTcorpo tivesse um Content-Type: application/jsontipo de mídia, mas o aceitou POSTcomo application/x-www-form-urlencodedcom um parâmetro chamado json(ou qualquer outro) cujo valor são os dados JSON
Como corrigir os problemas do cabeçalho "Acesso-controle-permissão-origem" não deve ser o curinga
Estou recebendo outra mensagem de erro:
O valor do cabeçalho 'Access-Control-Allow-Origin' na resposta não deve ser o curinga '*' quando o modo de credenciais da solicitação for 'include'. Portanto, a origem ' http://127.0.0.1:3000 ' não é permitida. O modo de credenciais de solicitações iniciadas pelo XMLHttpRequest é controlado pelo atributo withCredentials.
Para uma solicitação que inclui credenciais, os navegadores não permitirão que o código JavaScript do front-end acesse a resposta se o valor do Access-Control-Allow-Origincabeçalho da resposta for *. Em vez disso, o valor nesse caso deve corresponder exatamente à origem do seu código de front-end http://127.0.0.1:3000,.
Consulte Solicitações credenciadas e curingas no artigo MDN HTTP access control (CORS).
Se você controla o servidor para o qual está enviando a solicitação, uma maneira comum de lidar com esse caso é configurar o servidor para pegar o valor do Origincabeçalho da solicitação e repetir / refletir isso no valor do Access-Control-Allow-Origincabeçalho da resposta. Por exemplo, com nginx:
add_header Access-Control-Allow-Origin $http_origin
Mas esse é apenas um exemplo; outros sistemas de servidor (web) fornecem maneiras semelhantes de ecoar valores de origem.
Estou usando o Chrome. Eu também tentei usar o Chrome CORS Plugin
Esse plug-in do Chrome CORS aparentemente injeta simplesmente um Access-Control-Allow-Origin: *cabeçalho na resposta que o navegador vê. Se o plug-in fosse mais inteligente, o que estaria fazendo seria definir o valor desse Access-Control-Allow-Origincabeçalho de resposta falsa para a origem real do seu código JavaScript de front-end http://127.0.0.1:3000,.
Portanto, evite usar esse plug-in, mesmo para testes. É apenas uma distração. Se você deseja testar quais respostas você obtém do servidor sem que o navegador as filtre, é melhor usá-lo curl -Hcomo acima.
Quanto ao código JavaScript de front-end para a fetch(…)solicitação na pergunta:
headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
headers.append('Access-Control-Allow-Credentials', 'true');
Remova essas linhas. Os Access-Control-Allow-*cabeçalhos são cabeçalhos de resposta . Você nunca deseja enviá-los em uma solicitação. O único efeito que isso terá é acionar um navegador para realizar um preflight.