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.