I'estou tentando pegar alguns dados do REST API da HP Alm. Funciona muito bem com um pequeno script de ondulação - eu recebo meus dados.
Agora fazer isso com JavaScript, fetch e ES6 (mais ou menos) parece ser uma questão maior. Eu continuo a receber esta mensagem de erro:
Fetch API cannot load < URL>. Resposta ao pedido de pré-vôo doesn't passar a verificação de controle de acesso: No 'Access-Control-Allow-Origin' cabeçalho é presente no recurso solicitado. Origem 'http://127.0.0.1:3000' é portanto, não é permitido o acesso. A resposta tinha o código de status HTTP 501. Se uma resposta opaca atende às suas necessidades, defina o modo de pedido's para ' no-cors' para ir buscar o recurso com CORS desabilitado.
Entendo que isso é porque estou tentando obter esses dados dentro do meu local de hospedagem e a solução deveria ser usar CORS. Agora eu pensei que realmente fiz isso, mas de alguma forma ou ignora o que eu escrevo no cabeçalho ou o problema é outra coisa?
Então, há algum problema de implementação? Estou a fazer isto mal? Eu posso't verificar os logs do servidor infelizmente. I'estou realmente um pouco presa aqui.
function performSignIn() {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Accept', 'application/json');
headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
headers.append('Access-Control-Allow-Credentials', 'true');
headers.append('GET', 'POST', 'OPTIONS');
headers.append('Authorization', 'Basic ' + base64.encode(username + ":" + password));
fetch(sign_in, {
//mode: 'no-cors',
credentials: 'include',
method: 'POST',
headers: headers
})
.then(response => response.json())
.then(json => console.log(json))
.catch(error => console.log('Authorization failed : ' + error.message));
}
Estou a usar o cromado. Eu também tentei usar o Chrome CORS Plugin, mas depois estou recebendo outra mensagem de erro:
O valor do ' Access-Control-Allow-Origin' cabeçalho na resposta não deve ser o wildcard '*' quando o modo de credenciais do pedido's é ' incluir'. Origin 'http://127.0.0.1:3000' portanto não é permitido acesso. O modo de credenciais dos pedidos iniciados pelo XMLHttpRequest é controlado pelo atributo withCredentials.
Esta resposta cobre muito terreno, por isso está dividida em três partes:
*Como usar um proxy CORS para se locomover "No Access-Control-Allow-Origin header "* Problemas*** Se você não controla o servidor para o qual o seu código JavaScript do frontend está enviando uma solicitação, e o problema com a resposta desse servidor é apenas a falta do cabeçalho necessário 'Access-Control-Allow-Origin', você ainda pode fazer com que as coisas funcionem, fazendo a solicitação através de um proxy CORS. Para mostrar como isso funciona, primeiro aqui está um código que não utiliza 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 bloco catch
é atingido lá é que o navegador impede que esse código acesse a resposta que vem de https://example.com
. E o motivo pelo qual o navegador faz isso é que a resposta não tem o cabeçalho de resposta `Access-Control-Allow-Origin'.
Agora, aqui está exatamente o mesmo exemplo, mas apenas com um proxy CORS adicionado:
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?"))
Se o https
https://example.com
.Access-Control-Allow-Origin
é o que o browser vê.
Você pode facilmente executar seu próprio proxy usando o código de https://github.com/Rob--W/cors-anywhere/.git clone https://github.com/Rob--W/cors-anywhere.git
cd cors-anywhere/
npm install
heroku create
git push heroku master
https://cors-anywhere.herokuapp.com', prefira-a com a URL da sua própria instância; por exemplo, https://cryptic-headland-94862.herokuapp.com/https://example.com. **Então se quando você for tentar usar https<nolink>://cors-anywhere.herokuapp.com, você achar que está em baixo** (o que algumas vezes será), então considere obter uma conta Heroku (se você ainda não o fez) e leve 2 ou 3 minutos para fazer os passos acima para implantar seu próprio servidor CORS Anywhere no Heroku. Independentemente de você rodar seu próprio servidor ou utilizar https://cors-anywhere.herokuapp.com ou outro proxy aberto, esta solução irá funcionar mesmo se a requisição for uma requisição que acione os navegadores para fazer uma pré-vôo CORS
OPÇÕES, pois nesse caso, o proxy também envia de volta os cabeçalhos
Access-Control-Allow-Headers' e `Access-Control-Allow-Methods' necessários para fazer a pré-vôo com sucesso.**Como evitar o pré-voo CORS***
O código na pergunta aciona um pré-voo CORS - desde que ele envie um cabeçalho de "Autorização".
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests
Mesmo sem isso, o Content-Type: application/json
header também acionaria o pré-vôo.
O que "preflight" significa: antes do navegador tentar o POST
no código da pergunta, ele primeiro enviará uma solicitação de OPTIONS
ao servidor - para determinar se o servidor está optando por receber um POST
de origem cruzada que inclui os cabeçalhos Authorization
e Content-Type: application/json
.
Funciona muito bem com um pequeno script de ondulação - eu recebo meus dados. Para testar corretamente com o
curl', você precisa emular o pedido de pré-vôo
OPTIONS' 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"
...com https://the.sign_in.url
substituído por qualquer que seja o seu verdadeiro sign_in
URL.
A resposta que o navegador precisa ver a partir desse pedido de OPTIONS
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 resposta OPÇÕES
não incluir esses cabeçalhos, então o navegador irá parar por aí mesmo e nunca tentará sequer enviar o pedido POST
. Além disso, o código de status HTTP da resposta deve ser um 2xx-typically 200 ou 204. Se for qualquer outro código de status, o navegador vai parar por aí mesmo.
O servidor na questão está respondendo à solicitação OPTIONS' com um código de status 501, o que aparentemente significa que ele está tentando indicar que não implementa suporte a solicitações
OPTIONS'. Outros servidores normalmente respondem com um código de status 405 "Método não permitido" neste caso.
Então você nunca será capaz de fazer pedidos POST
diretamente a esse servidor a partir do seu código frontend JavaScript se o servidor responder a esse pedido OPTIONS
com um 405 ou 501 ou qualquer coisa que não seja 200 ou 204 ou se não responder com esses cabeçalhos de resposta necessários.
A maneira de evitar o disparo de um preflight para o caso na pergunta seria:
Autorização
mas, em vez disso (por exemplo) confiasse nos dados de autenticação embutidos no corpo da requisição POST
ou como um parâmetro de consultaPOST
tivesse um tipo de mídia Content-Type: application/json
mas, em vez disso, aceitasse o corpo POST
como application/x-www-form-urlencoded
com um parâmetro chamado json
(ou qualquer outro) cujo valor são os dados JSONComo corrigir "Access-Control-Allow-Origin header must not be the wildcard " problems
estou a receber outra mensagem de erro:
O valor do ' Access-Control-Allow-Origin' cabeçalho na resposta não deve ser o wildcard '' quando o modo de credenciais do pedido's é ' include'. Origin 'http://127.0.0.1:3000' portanto não é permitido acesso. O modo de credenciais dos pedidos iniciados pelo XMLHttpRequest é controlado pelo atributo withCredentials. Para uma solicitação que inclui credenciais, os navegadores não permitirão que o seu código JavaScript frontend acesse a resposta se o valor do cabeçalho de resposta
Access-Control-Allow-Origin
for `. Em vez disso, o valor nesse caso deve corresponder exatamente à origem do seu código front-end,
http://127.0.0.1:3000'. Veja Requisitos de credenciais e wildcards no artigo MDN HTTP access control (CORS). Se você controla o servidor para o qual está enviando a requisição, então uma maneira comum de lidar com este caso é configurar o servidor para pegar o valor do cabeçalho da requisiçãoOrigin', e ecoar/refletir isso de volta para o valor do cabeçalho da resposta
Access-Control-Allow-Origin'. Por exemplo, com nginx:
add_header Access-Control-Allow-Origin $http_origin
estou a usar o Cromo. Eu também tentei usar o Chrome CORS Plugin Aquele plugin Chrome CORS aparentemente apenas injecta de forma simples um
Access-Control-Allow-Origin': *
cabeçote na resposta que o navegador vê. Se o plugin fosse mais inteligente, o que estaria a fazer seria definir o valor desse falso cabeçalho de respostaAccess-Control-Allow-Origin' para a origem real do seu código frontend JavaScript,
http://127.0.0.1:3000'. Portanto, evite usar esse plugin, mesmo para testes. É apenas uma distracção. Se você quiser testar quais respostas você obtém do servidor sem filtragem do navegador, é melhor usar ocurl -H
como acima.No que diz respeito ao frontend do código JavaScript para a solicitação
fetch(...)
na pergunta:
headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
headers.append('Access-Control-Allow-Credentials', 'true');
Retire essas linhas. Os cabeçalhos Access-Control-Allow-*
são cabeçalhos responsáveis. Você nunca quer enviá-los em um pedido. O único efeito que terá é acionar um navegador para fazer um pré-voo.
Este erro ocorre quando a URL do cliente e a URL do servidor don't correspondem, incluindo o número da porta. Neste caso, você precisa habilitar seu serviço para CORS que é compartilhamento de recursos de origem cruzada.
Se você está hospedando um serviço Spring REST então você pode encontrá-lo no post do blog CORS support in Spring Framework.
Se você está hospedando um serviço usando um servidor Node.js, então
Pare o servidor do Node.js.
Instalar o corsnpm --save'.
Adicione as seguintes linhas ao seu server.js
var cors = require('cors')
app.use(cors()) // Use isto após a declaração da variável