Usando um cabeçalho de autorização com Buscar no React Native

140

Estou tentando usar o fetchReact Native para obter informações da API do Product Hunt. Obtive o token de acesso adequado e salvei-o em State, mas não consigo transmiti-lo no cabeçalho de autorização para uma solicitação GET.

Aqui está o que eu tenho até agora:

var Products = React.createClass({
  getInitialState: function() {
    return {
      clientToken: false,
      loaded: false
    }
  },
  componentWillMount: function () {
    fetch(api.token.link, api.token.object)
      .then((response) => response.json())
      .then((responseData) => {
          console.log(responseData);
        this.setState({
          clientToken: responseData.access_token,
        });
      })
      .then(() => {
        this.getPosts();
      })
      .done();
  },
  getPosts: function() {
    var obj = {
      link: 'https://api.producthunt.com/v1/posts',
      object: {
        method: 'GET',
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json',
          'Authorization': 'Bearer ' + this.state.clientToken,
          'Host': 'api.producthunt.com'
        }
      }
    }
    fetch(api.posts.link, obj)
      .then((response) => response.json())
      .then((responseData) => {
        console.log(responseData);
      })
      .done();
  },

A expectativa que tenho para o meu código é a seguinte:

  1. Primeiro, vou fetchacessar um token com dados do meu módulo API importado
  2. Depois disso, definirei a clientTokenpropriedade this.stateigual ao token de acesso recebido.
  3. Em seguida, executarei o getPostsque deve retornar uma resposta contendo uma matriz de postagens atuais do Product Hunt.

Posso verificar se o token de acesso está sendo recebido e se está sendo recebido this.statecomo sua clientTokenpropriedade. Também posso verificar se getPostsestá sendo executado.

O erro que estou recebendo é o seguinte:

{"error": "unauthorized_oauth", "error_description": "Forneça um token de acesso válido. Consulte a documentação da API sobre como autorizar uma solicitação de API. Verifique também se você precisa dos escopos corretos. Por exemplo, \" private public \ "para acessar pontos de extremidade privados."}

Estou trabalhando com a suposição de que, de alguma forma, não estou passando o token de acesso corretamente no cabeçalho da minha autorização, mas não consigo descobrir exatamente o porquê.

Richard Kho
fonte
2
Conforme observado neste SO , os cabeçalhos devem ser minúsculos (alguns servidores respeitam isso, outros não.) Eu apenas compartilho porque fui mordido por não conhecer a mim mesmo (e perdi tempo tentando depurar o problema.) É lamentável que tantos projetos, exemplos e artigos parecem não respeitar isso.
tj 25/05
Os nomes dos cabeçalhos @tj não diferenciam maiúsculas de minúsculas, e é exatamente isso que a resposta + superior aceita diz na pergunta que você vinculou.
coreyward

Respostas:

194

Exemplo de busca com cabeçalho de autorização:

fetch('URL_GOES_HERE', { 
   method: 'post', 
   headers: new Headers({
     'Authorization': 'Basic '+btoa('username:password'), 
     'Content-Type': 'application/x-www-form-urlencoded'
   }), 
   body: 'A=1&B=2'
 });
Cody Moniz
fonte
4
Isso não está funcionando para mim. O 'Authorization'cabeçalho silenciosamente falha ao anexar por firebug. Eu até tentei incluir credentials: 'include'no objeto opcional.
Ronnie Royston
7
@RonRoyston você está olhando para a chamada de OPÇÕES? se o terminal da API não tiver o CORS ativado (Access-Control-Allow-Origin: * se estiver acessando de um domínio diferente), poderá falhar na chamada OPTIONS.
Cody Moniz #
1
O ponto de extremidade da API não tem o CORS ativado, provavelmente é por isso que não funcionou para mim. Obrigado. Acabei instalando o complemento 'cors everywhere' para o firefox e funcionou.
Ronnie Royston
3
Sobre o problema que o RonRoyston está vendo, é necessário importar a biblioteca btoa , que não é nativa do nó. (É uma porta da biblioteca do navegador.) Caso contrário, a criação do cabeçalho de autenticação falha silenciosamente. Estávamos experimentando a mesma coisa.
Freewalker
2
developer.mozilla.org/pt-BR/docs/Web/API/Fetch_API/Using_Fetch por documentos, precisa new Headers()
agrupar
67

Acontece que eu estava usando o fetchmétodo incorretamente.

fetch espera dois parâmetros: um terminal para a API e um objeto opcional que possa conter corpo e cabeçalhos.

Eu estava envolvendo o objeto pretendido em um segundo objeto, o que não me deu o resultado desejado.

Veja como fica em alto nível:

fetch('API_ENDPOINT', OBJECT)  
  .then(function(res) {
    return res.json();
   })
  .then(function(resJson) {
    return resJson;
   })

Eu estruturei meu objeto como tal:

var obj = {  
  method: 'POST',
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json',
    'Origin': '',
    'Host': 'api.producthunt.com'
  },
  body: JSON.stringify({
    'client_id': '(API KEY)',
    'client_secret': '(API SECRET)',
    'grant_type': 'client_credentials'
  })
Richard Kho
fonte
você poderia talvez fornecer o código que está funcionando agora? Estou tentando usar a busca com um cabeçalho de autorização e não acho que meu código de autenticação esteja sendo passado como cabeçalho, porque estou recebendo uma 401resposta.
GoldenBeet 4/08
2
Feito, espero que seja útil.
Richard Kho
1
Oh, eu estive no seu site pessoal com esse exemplo! Foi assim que modelei o meu pela primeira vez. Eu descobri o meu problema, porém, era apenas porque meu URL estava errado. Foi necessária uma /no final que eu estava faltando ...
GoldenBeet
1
Obrigado, isso foi útil. Vale ressaltar que, embora a documentação de busca indique que a busca não manipula cookies, você também pode adicionar manualmente cookies ao cabeçalho com esse código. Apenas salve o uid e a chave e faça algo como: var obj = {method: 'GET', headers: {'Accept': 'application / json', 'Content-Type': 'application / json', 'Cookie': 'uid =' + uid + '; key = '+ tecla});
Dustin
8

Eu tive esse problema idêntico, estava usando o django-rest-knox para tokens de autenticação. Acontece que nada estava errado com o meu método de busca, que era assim:

...
    let headers = {"Content-Type": "application/json"};
    if (token) {
      headers["Authorization"] = `Token ${token}`;
    }
    return fetch("/api/instruments/", {headers,})
      .then(res => {
...

Eu estava correndo apache.

O que resolveu este problema para mim foi mudando WSGIPassAuthorizationpara 'On'nos wsgi.conf.

Eu tinha um aplicativo Django implantado no AWS EC2 e usei o Elastic Beanstalk para gerenciar meu aplicativo, então, no seguinte django.config, fiz o seguinte:

container_commands:
  01wsgipass:
    command: 'echo "WSGIPassAuthorization On" >> ../wsgi.conf'
Marquistador
fonte
0
completed = (id) => {
    var details = {
        'id': id,

    };

    var formBody = [];
    for (var property in details) {
        var encodedKey = encodeURIComponent(property);
        var encodedValue = encodeURIComponent(details[property]);
        formBody.push(encodedKey + "=" + encodedValue);
    }
    formBody = formBody.join("&");

    fetch(markcompleted, {
        method: 'POST',
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/x-www-form-urlencoded'
        },
        body: formBody
    })
        .then((response) => response.json())
        .then((responseJson) => {
            console.log(responseJson, 'res JSON');
            if (responseJson.status == "success") {
                console.log(this.state);
                alert("your todolist is completed!!");
            }
        })
        .catch((error) => {
            console.error(error);
        });
};
lilash sah
fonte