Permitir cabeçalho Access-Control-Allow-Origin usando HTML5 fetch API


87

Estou usando a API de busca HTML5.

var request = new Request('https://davidwalsh.name/demo/arsenal.json');

fetch(request).then(function(response) {
    // Convert to JSON
    return response.json();
}).then(function(j) {
    // Yay, `j` is a JavaScript object
    console.log(JSON.stringify(j));
}).catch(function(error) {
    console.log('Request failed', error)
});

Consigo usar o json normal, mas não consigo buscar os dados do URL da API acima. Ele gera um erro:

A API de busca não pode carregar https://davidwalsh.name/demo/arsenal.json . Nenhum cabeçalho 'Access-Control-Allow-Origin' está presente no recurso solicitado. Portanto, o acesso de origem ' http: // localhost ' não é permitido. Se uma resposta opaca atender às suas necessidades, defina o modo da solicitação como 'no-cors' para buscar o recurso com o CORS desativado.


O servidor de terceiros precisa configurá-lo, não há nada que você possa fazer no lado do cliente.
epascarello

@epascarello: Podemos fazer no lado do cliente. Nos bastidores, a solicitação XHR está em andamento. Por favor, verifique istohttps://davidwalsh.name/fetch
iNikkz

Respostas:


81

Como disse epascarello, o servidor que hospeda o recurso precisa ter o CORS habilitado. O que você pode fazer no lado do cliente (e provavelmente no que você está pensando) é definir o modo de busca para CORS (embora esta seja a configuração padrão, eu acredito):

fetch(request, {mode: 'cors'});

No entanto, isso ainda requer que o servidor habilite o CORS também e permita que seu domínio solicite o recurso.

Confira a documentação do CORS e este incrível vídeo Udacity explicando a política da mesma origem .

Você também pode usar o modo no-cors no lado do cliente, mas isso apenas fornecerá uma resposta opaca (você não pode ler o corpo, mas a resposta ainda pode ser armazenada em cache por um service worker ou consumida por algumas APIs, como <img>) :

fetch(request, {mode: 'no-cors'})
.then(function(response) {
  console.log(response); 
}).catch(function(error) {  
  console.log('Request failed', error)  
});

2
você pode explicar "No entanto, isso ainda requer que o servidor habilite o CORS também e permita que seu domínio solicite o recurso."? Tenho procurado sem sucesso instruções para fazer isso.
jayscript

2
@jayscript o processo geral se parece com isto: no cliente, uma solicitação de origem cruzada é feita com javascript. No caso da API de busca, o modo 'cors' informa ao navegador que está tudo bem para fazer essa solicitação. Se você tivesse o modo 'no-cors', o navegador interromperia a solicitação, porque ela não é a origem do seu aplicativo. O servidor receberá a solicitação e responderá. O navegador confirma que a resposta possui os cabeçalhos CORS apropriados e, em caso afirmativo, permite que a resposta seja lida. Se os cabeçalhos não estiverem presentes, o navegador gerará um erro.
David Scales de

1
@jayscript este artigo MDN entra em detalhes. Essencialmente, em seu servidor, você precisa definir estes cabeçalhos: "Access-Control-Allow-Origin: foo.example ", "Access-Control-Allow-Methods: POST, GET, OPTIONS", "Access-Control-Allow-Headers: X-PINGOTHER, Content-Type ", que permite origens, métodos e cabeçalhos, respectivamente. Normalmente, '*' é usado para o cabeçalho de origem. Você também pode verificar este documento do Google e codelab associado para aprender sobre a API Fetch: developers.google.com/web/ilt/pwa/working-with-the-fetch-api
David Scales

2
Obrigado! Isso me ajuda a entender que é impossível buscar dados do servidor API que tenham uma origem diferente quando o servidor API não contém nenhum cabeçalho. No caso específico que estava tratando, tive acesso ao código do servidor da API e fui capaz de adicionar cabeçalhos sozinho, o que permitiu a busca.
jayscript de

Isso é burro, qual é o problema de segurança com NO sendingcookies e, portanto, permitindo CORS?
deathangel908 de

14

Eu tinha meu código de front-end em http: // localhost: 3000 e minha API (código de back-end) em http: // localhost: 5000

Estava usando fetch API para chamar a API. Inicialmente, ele estava jogando o erro "cors". Em seguida, adicionei o código abaixo em meu código da API Backend, permitindo origem e cabeçalho de qualquer lugar.

let allowCrossDomain = function(req, res, next) {
  res.header('Access-Control-Allow-Origin', "*");
  res.header('Access-Control-Allow-Headers', "*");
  next();
}
app.use(allowCrossDomain);

No entanto, você deve restringir suas origens no caso de outros ambientes como stage, prod.


20
esta é uma resposta terrível. este é um grande problema de segurança. se você está lendo isso, POR FAVOR, NÃO FAÇA ISSO.
mjones.udri de

1
Isso é apenas para a configuração local. Por exemplo, para fazer um tipo de foto rápida. Sim, há um risco de segurança se o mesmo for para outros ambientes implantáveis. Para local, eu sinto que não. "No entanto, você deve restringir as origens de você no caso de outros ambientes como palco, prod"
smsivaprakaash

12

Isso funcionou para mim:

npm install -g local-cors-proxy

Endpoint de API que desejamos solicitar e que tem problemas de CORS:

https://www.yourdomain.com/test/list

Iniciar Proxy:

lcp --proxyUrl https://www.yourdomain.com

 Proxy Active 

 Proxy Url: http://www.yourdomain.com:28080
 Proxy Partial: proxy
 PORT: 8010

Em seguida, em seu código de cliente, novo endpoint de API:

http://localhost:8010/proxy/test/list

O resultado final será uma solicitação para https://www.yourdomain.ie/test/list sem os problemas do CORS!


Por favor, certifique-se de que o servidor está executando paralelamente. Abra uma nova janela cmt-prompt e execute o código lcp --proxyUrl yourdomain.com
Govarthanan Venunathan

8

Sei que esta é uma postagem mais antiga, mas descobri que o que funcionou para corrigir esse erro foi usar o endereço IP do meu servidor em vez de usar o nome de domínio na minha solicitação de busca. Então, por exemplo:

#(original) var request = new Request('https://davidwalsh.name/demo/arsenal.json');
#use IP instead
var request = new Request('https://0.0.0.0/demo/arsenal.json');

fetch(request).then(function(response) {
    // Convert to JSON
    return response.json();
}).then(function(j) {
    // Yay, `j` is a JavaScript object
    console.log(JSON.stringify(j));
}).catch(function(error) {
    console.log('Request failed', error)
});

1

Se você estiver usando o nginx, tente isso

#Control-Allow-Origin access

    # Authorization headers aren't passed in CORS preflight (OPTIONS) calls. Always return a 200 for options.
    add_header Access-Control-Allow-Credentials "true" always;
    add_header Access-Control-Allow-Origin "https://URL-WHERE-ORIGIN-FROM-HERE " always;
    add_header Access-Control-Allow-Methods "GET,OPTIONS" always;
    add_header Access-Control-Allow-Headers "x-csrf-token,authorization,content-type,accept,origin,x-requested-with,access-control-allow-origin" always;

    if ($request_method = OPTIONS ) {
        return 200;
    }


Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.