Использование заголовка авторизации с Fetch в React Native

141

Я пытаюсь использовать fetchв React Native, чтобы получить информацию из API поиска продуктов. Я получил правильный токен доступа и сохранил его в состояние, но, похоже, не смог передать его в заголовке авторизации для запроса GET.

Вот что у меня так далеко:

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

Ожидание, которое я имею для моего кода, следующее:

  1. Сначала я fetchполучу токен доступа с данными из моего импортированного модуля API
  2. После этого я установлю clientTokenсвойство this.stateравным полученному токену доступа.
  3. Затем я запущу, getPostsкоторый должен вернуть ответ, содержащий массив текущих сообщений от Product Hunt.

Я могу проверить, что токен доступа получен и что this.stateон получает его в качестве своего clientTokenсвойства. Я также могу проверить, getPostsчто выполняется.

Я получаю следующую ошибку:

{"error": "unauthorized_oauth", "error_description": "Пожалуйста, предоставьте действительный токен доступа. Обратитесь к нашей документации api о том, как авторизовать запрос api. Также убедитесь, что вам требуются правильные области. Например," public public \ " "для доступа к частным конечным точкам."}

Я работал над предположением, что я как-то неправильно передаю токен доступа в своем заголовке авторизации, но, похоже, не могу точно понять, почему.

Ричард Хо
источник
2
Как отмечено в этой статье , заголовки предназначены для строчных букв (некоторые серверы уважают это, другие - нет). Я делюсь ими только потому, что меня укусило то, что я сам не знал (и потратил время на попытки отладить проблему.) К сожалению, так много проектов, примеров и статей, кажется, не уважают это.
TJ
@tj Имена заголовков не чувствительны к регистру, и это именно то, что отвечает принятый + топ ответ на вопрос, который вы связали
Coreyward

Ответы:

195

Пример выборки с заголовком авторизации:

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'
 });
Коди Мониз
источник
4
Это не работает для меня. 'Authorization'Заголовок молча не удается пристроить в поджигатель. Я даже пытался включить credentials: 'include'в дополнительный объект.
Ронни Ройстон
7
@RonRoyston вы смотрите на звонок ОПЦИИ? если в конечной точке API не включена функция CORS (Access-Control-Allow-Origin: * при доступе из другого домена), это может привести к сбою при вызове OPTIONS.
Коди Мониз
1
В конечной точке API не включена поддержка CORS, поэтому, вероятно, она и не сработала. Спасибо. Я закончил тем, что установил дополнение для cors везде для firefox, и это сработало.
Ронни Ройстон
3
В связи с проблемой @RonRoyston необходимо импортировать библиотеку btoa , которая не является нативной для узла. (Это порт браузера lib.) В противном случае создание заголовка аутентификации завершается неудачно. Мы переживали то же самое.
Freewalker
2
developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch для документов, необходимо обернуть заголовки сnew Headers()
Даниэль Дубовски
67

Оказывается, я использовал fetchметод неправильно.

fetch ожидается два параметра: конечная точка для API и необязательный объект, который может содержать тело и заголовки.

Я обернул предполагаемый объект во второй объект, который не дал мне желаемого результата.

Вот как это выглядит на высоком уровне:

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

Я структурировал свой объект так:

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'
  })
Ричард Хо
источник
не могли бы вы предоставить сейчас работающий код? Я пытаюсь использовать fetch с заголовком авторизации и не думаю, что мой код авторизации передается в качестве заголовка, потому что я получаю 401ответ.
GoldenBeet
2
Готово, надеюсь, это будет полезно
Ричард Хо
1
О, я был на вашем личном сайте с этим примером! Вот как я смоделировал свой первый раз. Я понял свою проблему, хотя, это просто, что мой URL был неправильным. Это потребовало /в конце, что я пропустил ...
GoldenBeet
1
Спасибо, это было полезно. Стоит отметить, что, хотя документация по выборке указывает, что выборка не обрабатывает файлы cookie, вы можете вручную добавить файлы cookie в заголовок с помощью этого кода. Просто сохраните uid и ключ и сделайте что-то вроде: var obj = {method: 'GET', заголовки: {'Accept': 'application / json', 'Content-Type': 'application / json', 'Cookie': 'UID =' + UID + "; ключ = '+ ключ});
Дастин
8

У меня была такая же проблема, я использовал django-rest-knox для токенов аутентификации. Оказывается, ничего не случилось с моим методом извлечения, который выглядел так:

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

Я работал Apache.

Что решить эту проблему для меня изменения WSGIPassAuthorizationв 'On'в wsgi.conf.

У меня было приложение Django, развернутое на AWS EC2, и я использовал Elastic Beanstalk для управления своим приложением, поэтому django.configя сделал это:

container_commands:
  01wsgipass:
    command: 'echo "WSGIPassAuthorization On" >> ../wsgi.conf'
Marquistador
источник
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);
        });
};
лилаш сах
источник