Verwenden eines Autorisierungsheaders mit Fetch in React Native

139

Ich versuche, fetchin React Native Informationen aus der Product Hunt-API abzurufen. Ich habe das richtige Zugriffstoken erhalten und im Status gespeichert, kann es jedoch anscheinend nicht im Autorisierungsheader für eine GET-Anforderung weitergeben.

Folgendes habe ich bisher:

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

Die Erwartung, die ich an meinen Code habe, ist folgende:

  1. Zuerst werde ich fetchein Zugriffstoken mit Daten aus meinem importierten API-Modul erstellen
  2. Danach setze ich die clientTokenEigenschaft von so this.state, dass sie dem empfangenen Zugriffstoken entspricht.
  3. Dann werde ich ausführen, getPostswas eine Antwort zurückgeben sollte, die eine Reihe aktueller Beiträge von Product Hunt enthält.

Ich kann überprüfen, ob das Zugriffstoken empfangen wird und ob this.statees als seine clientTokenEigenschaft empfangen wird . Ich kann auch überprüfen, ob das ausgeführt getPostswird.

Der Fehler, den ich erhalte, ist folgender:

{"error": "unauthorized_oauth", "error_description": "Bitte geben Sie ein gültiges Zugriffstoken an. Informationen zum Autorisieren einer API-Anfrage finden Sie in unserer API-Dokumentation. Stellen Sie außerdem sicher, dass Sie die richtigen Bereiche benötigen. Beispiel:" private public \ " "für den Zugriff auf private Endpunkte."}

Ich habe die Annahme getroffen, dass ich das Zugriffstoken in meinem Autorisierungsheader irgendwie nicht richtig weitergebe, aber anscheinend nicht genau herausfinden kann, warum.

Richard Kho
quelle
2
Wie in dieser SO erwähnt , sollen Header in Kleinbuchstaben geschrieben sein (einige Server respektieren dies, andere nicht). Ich teile sie nur, weil ich davon gebissen wurde, ohne mich selbst zu kennen (und Zeit damit verschwendet habe, das Problem zu debuggen). Es ist bedauerlich, dass so viele Projekte, Beispiele und Artikel scheinen dies nicht zu respektieren.
tj
@tj Header-Namen unterscheiden nicht zwischen Groß- und Kleinschreibung, und genau das sagt die akzeptierte + Top-Antwort auf die von Ihnen verknüpfte Frage.
Coreyward

Antworten:

194

Beispielabruf mit Berechtigungsheader:

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
quelle
4
Das funktioniert bei mir nicht. Der 'Authorization'Header kann laut Firebug nicht automatisch angehängt werden. Ich habe sogar versucht, credentials: 'include'in das optionale Objekt aufzunehmen.
Ronnie Royston
7
@ RonRoyston schaust du dir den OPTIONS-Aufruf an? Wenn auf dem API-Endpunkt CORS nicht aktiviert ist (Access-Control-Allow-Origin: * beim Zugriff von einer anderen Domäne), schlägt dies möglicherweise beim Aufruf von OPTIONS fehl.
Cody Moniz
1
Auf dem API-Endpunkt ist CORS nicht aktiviert, daher hat es bei mir wahrscheinlich nicht funktioniert. Vielen Dank. Am Ende habe ich das Add-On "Cors überall" für Firefox installiert und es hat funktioniert.
Ronnie Royston
3
Wenn das Problem bei @RonRoyston auftritt, müssen Sie die btoa-Bibliothek importieren , die nicht für den Knoten nativ ist. (Dies ist ein Port einer Browser-Bibliothek.) Andernfalls schlägt die Erstellung des Auth-Headers im Hintergrund fehl. Wir haben das Gleiche erlebt.
Freewalker
2
developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch per docs, müssen Header mitnew Headers()
Daniel Dubovski
67

Es stellte sich heraus, dass ich die fetchMethode falsch angewendet habe.

fetch erwartet zwei Parameter: einen Endpunkt für die API und ein optionales Objekt, das Body und Header enthalten kann.

Ich wickelte das beabsichtigte Objekt in ein zweites Objekt ein, was mir kein gewünschtes Ergebnis brachte.

So sieht es auf hohem Niveau aus:

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

Ich habe mein Objekt so strukturiert:

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
quelle
Könnten Sie vielleicht den jetzt funktionierenden Code bereitstellen? Ich versuche, Fetch mit einem Autorisierungsheader zu verwenden, und ich glaube nicht, dass mein Authentifizierungscode als Header übergeben wird, da ich eine 401Antwort erhalte.
GoldenBeet
2
Fertig, hoffe es ist hilfreich
Richard Kho
1
Oh, ich war mit diesem Beispiel auf Ihrer persönlichen Seite! So habe ich meine zum ersten Mal modelliert. Ich habe mein Problem herausgefunden, es war nur so, dass meine URL falsch war. Es erforderte ein /am Ende, dass ich vermisst wurde ...
GoldenBeet
1
Danke, das war hilfreich. Beachten Sie, dass in der Abrufdokumentation zwar darauf hingewiesen wird, dass beim Abrufen keine Cookies verarbeitet werden, Sie Cookies jedoch auch mit diesem Code manuell zum Header hinzufügen können. Speichern Sie einfach die UID und den Schlüssel und machen Sie etwas wie: var obj = {method: 'GET', headers: {'Accept': 'application / json', 'Content-Type': 'application / json', 'Cookie': 'uid =' + uid + '; key = '+ key});
Dustin
8

Ich hatte dieses identische Problem, ich verwendete Django-Rest-Knox für Authentifizierungstoken. Es stellt sich heraus, dass an meiner Abrufmethode, die so aussah, nichts falsch war:

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

Ich habe Apache ausgeführt.

Was dieses Problem für mich löste, war der Wechsel WSGIPassAuthorizationzu 'On'in wsgi.conf.

Ich hatte einen Django - App auf AWS EC2 eingesetzt, und ich Elastic Beanstalk meine Anwendung zu verwalten, so in der django.configich dies tat:

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