Używanie nagłówka autoryzacji z Fetch in React Native

141

Próbuję użyć fetchw React Native, aby pobrać informacje z API Product Hunt. Uzyskałem właściwy token dostępu i zapisałem go w stanie, ale wydaje się, że nie mogę go przekazać w nagłówku autoryzacji dla żądania GET.

Oto, co mam do tej pory:

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

Oczekiwania, jakie mam wobec mojego kodu, są następujące:

  1. Najpierw będę fetchtokenem dostępu z danymi z mojego zaimportowanego modułu API
  2. Następnie ustawię clientTokenwłaściwość this.staterówną otrzymanemu tokenowi dostępu.
  3. Następnie uruchomię, getPostsktóra powinna zwrócić odpowiedź zawierającą tablicę aktualnych postów z Product Hunt.

Jestem w stanie zweryfikować, czy token dostępu jest odbierany i czy this.stateotrzymuje go jako swoją clientTokenwłasność. Jestem również w stanie sprawdzić, czy getPostsjest uruchamiany.

Otrzymuję następujący błąd:

{"error": "unauthorized_oauth", "error_description": "Podaj prawidłowy token dostępu. Zapoznaj się z naszą dokumentacją API, aby dowiedzieć się, jak autoryzować żądanie API. Upewnij się również, że potrzebujesz poprawnych zakresów. Np. \" private public \ „w celu uzyskania dostępu do prywatnych punktów końcowych”.}

Odpracowałem założenie, że w jakiś sposób nie przekazuję poprawnie tokenu dostępu w nagłówku autoryzacji, ale nie potrafię dokładnie określić, dlaczego.

Richard Kho
źródło
2
Jak wspomniano w tym SO , nagłówki powinny być pisane małymi literami (niektóre serwery to szanują, inne nie). Udostępniam tylko dlatego, że ugryzło mnie to, nie wiedząc siebie (i straciłem czas na próbę debugowania problemu). Szkoda, że tak wiele projektów, przykładów i artykułów wydaje się tego nie uwzględniać.
tj
@tj W nazwach nagłówków nie jest rozróżniana wielkość liter i dokładnie tak mówi zaakceptowana + najlepsza odpowiedź na pytanie, które łączysz.
coreyward

Odpowiedzi:

195

Przykładowe pobieranie z nagłówkiem autoryzacji:

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
źródło
4
To nie działa dla mnie. 'Authorization'Nagłówek cicho nie przywiązują za Firebug. Próbowałem nawet dołączyć credentials: 'include'do opcjonalnego obiektu.
Ronnie Royston,
7
@RonRoyston. Patrzysz na wezwanie OPTIONS? jeśli punkt końcowy interfejsu API nie ma włączonego mechanizmu CORS (Access-Control-Allow-Origin: * w przypadku uzyskiwania dostępu z innej domeny), może to zakończyć się niepowodzeniem przy wywołaniu OPTIONS.
Cody Moniz
1
Punkt końcowy API nie ma włączonego CORS, więc prawdopodobnie dlatego nie zadziałał dla mnie. Dzięki. Skończyło się na zainstalowaniu dodatku „cors wszędzie” do przeglądarki Firefox i zadziałało.
Ronnie Royston,
3
Jeśli chodzi o problem, który widzi @RonRoyston, musisz zaimportować bibliotekę btoa , która nie jest natywna dla węzła. (Jest to port biblioteki przeglądarki.) W przeciwnym razie utworzenie nagłówka auth po cichu kończy się niepowodzeniem. Doświadczyliśmy tego samego.
Freewalker
2
developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch per docs, trzeba zawijać nagłówkinew Headers()
Daniel Dubovski
67

Okazuje się, że fetchźle użyłem tej metody.

fetch oczekuje dwóch parametrów: punktu końcowego API i opcjonalnego obiektu, który może zawierać treść i nagłówki.

Pakowałem wybrany obiekt w drugi obiekt, co nie przyniosło mi pożądanego rezultatu.

Oto jak to wygląda na wysokim poziomie:

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

Skonstruowałem mój obiekt jako taki:

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
źródło
czy możesz podać działający kod? Próbuję użyć funkcji pobierania z nagłówkiem autoryzacji i nie sądzę, aby mój kod autoryzacji był przekazywany jako nagłówek, ponieważ otrzymuję 401odpowiedź.
GoldenBeet
2
Gotowe, mam nadzieję, że to pomoże
Richard Kho
1
Och, byłem na twojej osobistej stronie z tym przykładem! Tak modelowałem swój pierwszy raz. Zrozumiałem jednak mój problem, po prostu mój adres URL był nieprawidłowy. Na /koniec brakowało mi ...
GoldenBeet
1
Dzięki, to było pomocne. Warto zauważyć, że chociaż dokumentacja pobierania wskazuje, że pobieranie nie obsługuje plików cookie, możesz ręcznie dodać pliki cookie do nagłówka również za pomocą tego kodu. Po prostu zapisz identyfikator i klucz i wykonaj coś takiego: var obj = {metoda: 'GET', headers: {'Accept': 'application / json', 'Content-Type': 'application / json', 'Cookie': 'uid =' + uid + '; key = '+ key});
Dustin
8

Miałem ten sam problem, używałem django-rest-knox do uwierzytelniania tokenów. Okazuje się, że nie było nic złego w mojej metodzie pobierania, która wyglądała tak:

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

Biegałem apache.

To, co rozwiązało ten problem, zmieniło się WSGIPassAuthorizationna 'On'w wsgi.conf.

Miałem aplikację Django wdrożoną na AWS EC2 i użyłem Elastic Beanstalk do zarządzania moją aplikacją, więc w programie django.configzrobiłem to:

container_commands:
  01wsgipass:
    command: 'echo "WSGIPassAuthorization On" >> ../wsgi.conf'
Marquistador
źródło
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
źródło