Utilisation d'un en-tête d'autorisation avec Fetch dans React Native

141

J'essaie d'utiliser fetchdans React Native pour récupérer des informations de l'API Product Hunt. J'ai obtenu le jeton d'accès approprié et je l'ai enregistré dans State, mais je ne semble pas pouvoir le transmettre dans l'en-tête d'autorisation pour une demande GET.

Voici ce que j'ai jusqu'à présent:

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();
  },

L'attente que j'ai pour mon code est la suivante:

  1. Tout d'abord, je vais fetchun jeton d'accès avec les données de mon module API importé
  2. Après cela, je définirai la clientTokenpropriété de this.statepour qu'elle égale le jeton d'accès reçu.
  3. Ensuite, je vais exécuter getPostsce qui devrait renvoyer une réponse contenant un tableau des publications actuelles de Product Hunt.

Je suis en mesure de vérifier que le jeton d'accès est reçu et qu'il le this.statereçoit comme sa clientTokenpropriété. Je suis également en mesure de vérifier que cela getPostsest en cours d'exécution.

L'erreur que je reçois est la suivante:

{"error": "unauthorized_oauth", "error_description": "Veuillez fournir un jeton d'accès valide. Reportez-vous à la documentation de notre API pour savoir comment autoriser une demande d'API. Veuillez également vous assurer que vous avez besoin des bonnes étendues. Par exemple, \" public privé \ "pour accéder aux points de terminaison privés."}

Je suis parti de l'hypothèse que je ne transmettrais pas correctement le jeton d'accès dans mon en-tête d'autorisation, mais je ne semble pas être en mesure de comprendre exactement pourquoi.

Richard Kho
la source
2
Comme indiqué dans cette SO , les en-têtes sont destinés à être en minuscules (certains serveurs respectent cela, d'autres non.) Je ne partage que parce que j'ai été mordu par cela sans me connaître (et j'ai perdu du temps à essayer de déboguer le problème.) Il est regrettable que tant de projets, d'exemples et d'articles ne semblent pas respecter cela.
tj
Les noms d'en-tête @tj ne sont pas sensibles à la casse, et c'est exactement ce que dit la réponse acceptée + supérieure sur la question que vous avez liée.
coreyward

Réponses:

195

Exemple de récupération avec en-tête d'autorisation:

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
la source
4
Cela ne fonctionne pas pour moi. L'en- 'Authorization'tête ne parvient pas silencieusement à se connecter par firebug. J'ai même essayé d'inclure credentials: 'include'dans l'objet optionnel.
Ronnie Royston
7
@RonRoyston regardez-vous l'appel OPTIONS? si CORS n'est pas activé sur le point de terminaison de l'API (Access-Control-Allow-Origin: * si vous accédez à partir d'un domaine différent), il peut échouer lors de l'appel OPTIONS.
Cody Moniz
1
api endpoint n'a pas activé CORS, c'est probablement pourquoi cela n'a pas fonctionné pour moi. Merci. J'ai fini par installer l'add-on «cors partout» pour Firefox et cela a fonctionné.
Ronnie Royston
3
Concernant le problème rencontré par @RonRoyston, vous devez importer la bibliothèque btoa , qui n'est pas native de node. (C'est un port d'une bibliothèque de navigateur.) Sinon, la création d'en-tête d'authentification échoue silencieusement. Nous vivions la même chose.
Freewalker
2
developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch par docs, besoin d' new Headers()
encapsuler les en-
67

Il s'avère que j'utilisais la fetchméthode de manière incorrecte.

fetch attend deux paramètres: un point de terminaison pour l'API et un objet facultatif qui peut contenir un corps et des en-têtes.

J'emballais l'objet prévu dans un deuxième objet, ce qui ne m'a pas donné le résultat souhaité.

Voici à quoi cela ressemble à un niveau élevé:

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

J'ai structuré mon objet comme tel:

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
la source
pourriez-vous peut-être fournir le code qui fonctionne maintenant? J'essaie d'utiliser fetch avec un en-tête d'autorisation et je ne pense pas que mon code d'authentification soit passé en tant qu'en-tête, car j'obtiens une 401réponse.
GoldenBeet
2
Fait, j'espère que c'est utile
Richard Kho
1
Oh, j'ai été sur votre site personnel avec cet exemple! C'est comme ça que j'ai modélisé le mien la première fois. J'ai compris mon problème, c'était juste que mon URL était erronée. Il fallait un /à la fin qu'il me manquait ...
GoldenBeet
1
Merci, cela a été utile. Il convient de noter que, bien que la documentation de récupération indique que la récupération ne gère pas les cookies, vous pouvez également ajouter manuellement des cookies à l'en-tête avec ce code. Enregistrez simplement l'uid et la clé et faites quelque chose comme: var obj = {method: 'GET', headers: {'Accept': 'application / json', 'Content-Type': 'application / json', 'Cookie': 'uid =' + uid + '; clé = '+ clé});
Dustin
8

J'ai eu ce problème identique, j'utilisais django-rest-knox pour les jetons d'authentification. Il s'avère que rien n'allait mal avec ma méthode de récupération qui ressemblait à ceci:

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

J'utilisais Apache.

Que résolu ce problème pour moi était de changer WSGIPassAuthorizationà 'On'en wsgi.conf.

J'avais une application Django déployée sur AWS EC2 et j'ai utilisé Elastic Beanstalk pour gérer mon application, donc dans le django.config, j'ai fait ceci:

container_commands:
  01wsgipass:
    command: 'echo "WSGIPassAuthorization On" >> ../wsgi.conf'
Marquistador
la source
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
la source