Извлечь как JSON, так и заголовки из fetch()

Я моделирую аутентификационный слой для простого приложения "Реакция / Избыток". На стороне сервера у меня есть API, основанный на геме devise_token_auth.

я использую fetch чтобы разместить знак в запросе:

const JSON_HEADERS = new Headers({
  'Content-Type': 'application/json'
});

export const postLogin = ({ email, password }) => fetch(
  `${API_ROOT}/v1/auth/sign_in`, {
    method: 'POST',
    headers: JSON_HEADERS,
    body: JSON.stringify({ email, password })
});

// postLogin({ email: 'test@test.it', password: 'whatever' });

Это работает, и я получаю ответ 200 и все данные, которые мне нужны. Моя проблема в том, что информация разделена между телом ответа и заголовками.

  • Body: информация о пользователе
  • Заголовки: токен доступа, срок действия и т. Д.

Я мог бы разобрать тело JSON следующим образом:

postLogin({ 'test@test.it', password: 'whatever' })
  .then(res => res.json())
  .then(resJson => dispatch(myAction(resJson))

Но потом myAction не получит никаких данных из заголовков (потерян при анализе JSON).

Есть ли способ получить заголовки и тело от fetch Запрос? Спасибо!

2 ответа

Решение

Я думал, что поделюсь тем, как мы наконец решили эту проблему: просто добавив шаг в .then цепочка (перед синтаксическим анализом JSON) для анализа заголовков аутентификации и отправки правильного действия:

fetch('/some/url')
  .then(res => {
    const authHeaders = ['access-token', 'client', 'uid']
      .reduce((result, key) => {
        let val = res.headers.get(key);
        if (val) {
          result[key] = val;
        }
      }, {});
    store.dispatch(doSomethingWith(authHeaders)); // or localStorage
    return res;
  })
  .then(res => res.json())
  .then(jsonResponse => doSomethingElseWith(jsonResponse))

Еще один подход, вдохновленный могущественным Даном Абрамовым ( /questions/2487077/kak-obrabatyivat-oshibki-v-otvetah-fetch-s-pomoschyu-redux-thunk/2487091#2487091)

fetch('/some/url')
  .then(res => res.json().then(json => ({
    headers: res.headers,
    status: res.status,
    json
  }))
.then({ headers, status, json } => goCrazyWith(headers, status, json));

НТН

Может быть так:

postLogin({ 'test@test.it', password: 'whatever' })
  .then(res => {
    processHeader(res.headers.raw())
    dispatch(myAction(res.json()))
  })

Если вы хотите проанализировать все заголовки в объект (а не сохранять итератор), вы можете сделать следующее (на основе подхода Дэна Абрамова выше):

fetch('https://jsonplaceholder.typicode.com/users')
    .then(res => (res.headers.get('content-type').includes('json') ? res.json() : res.text())
    .then(data => ({
        headers: [...res.headers].reduce((acc, header) => {
            return {...acc, [header[0]]: header[1]};
        }, {}),
        status: res.status,
        data: data,
    }))
    .then((headers, status, data) => console.log(headers, status, data)));

или в пределах async контекст / функция:

let response = await fetch('https://jsonplaceholder.typicode.com/users');

const data = await (
    response.headers.get('content-type').includes('json')
    ? response.json()
    : response.text()
);

response = {
    headers: [...response.headers].reduce((acc, header) => {
        return {...acc, [header[0]]: header[1]};
    }, {}),
    status: response.status,
    data: data,
};

приведет к:

{
    data: [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}],
    headers: {
        cache-control: "public, max-age=14400"
        content-type: "application/json; charset=utf-8"
        expires: "Sun, 23 Jun 2019 22:50:21 GMT"
        pragma: "no-cache"
    },
    status: 200
}

в зависимости от вашего варианта использования это может быть более удобно. Это решение также учитывает тип содержимого для вызова либо.json() или .text() на ответ.

Мое решение для WP json API

fetch(getWPContent(searchTerm, page))
  .then(response => response.json().then(json => ({
    totalPages: response.headers.get("x-wp-totalpages"),
    totalHits: response.headers.get("x-wp-total"),
    json
  })))
  .then(result => {
    console.log(result)
  })
Другие вопросы по тегам