Клиент Apollo, задерживающий заголовок авторизации

Я использую Apollo (с Graph Cool), redux и Auth0 в приложении React-Native. Я пытаюсь отложить запросы и мутации, пока не будет установлен заголовок.

IdToken хранится в Async Storage и поэтому является обещанием. Я не могу использовать избыточность для передачи токена, потому что это создаст круговую зависимость.

Когда пользователь входит в систему в первый раз или токен истек, запросы отправляются до установки заголовка, что означает, что я получаю ошибку Error: GraphQL error: Insufficient Permissions введите описание изображения здесь

Как я могу отложить запросы, пока токен не будет найден и добавлен в заголовок? Я искал три основных решения:

  1. Добавить forceFetch: true; Похоже, это является частью более ранней реализации клиента Apollo. Даже если я найду эквивалент, приложение все равно не сможет с первой попытки получить.
  2. Сбросьте хранилище (регидратируйте?) При входе в систему. Это все еще асинхронно, поэтому я не понимаю, как это может повлиять на результат.
  3. Удалите все мутации и запросы из самого логина, но из-за прогресса приложения это невозможно.

Некоторые фрагменты:

const token = AsyncStorage.getItem('token');
const networkInterface = createNetworkInterface({ uri:XXXX})

//adds the token in the header
networkInterface.use([{
    applyMiddleware(req, next) {
        if(!req.options.headers) {
            req.options.headers = {}
        }
        if(token) {
            token
                .then(myToken => {
                    req.options.headers.authorization = `Bearer ${myToken}`;
                })
                .catch(err => console.log(err));   
        }
        next(); // middleware so needs to allow the endpoint functions to run;
    },
}]);

// create the apollo client;
const client = new ApolloClient({
    networkInterface,
    dataIdFromObject: o => o.id
});

а также

const store = createStore(
  combineReducers({
    token: tokenReducer,
    profile: profileReducer,
    path: pathReducer,
    apollo: client.reducer(),
  }),
  {}, // initial state
  compose(
      applyMiddleware(thunk, client.middleware(), logger),
  )
);

1 ответ

Решение

Я не уверен, что это будет работать без приложения для воспроизведения, в основном потому, что у меня не настроено приложение с вашей структурой, но вы попали в это состояние гонки, потому что вы вызываете next() вне вашей асинхронной цепочки.

Вызов next() там, где он находится в данный момент, скажет клиенту продолжить выполнение запроса, даже если ваш токен не установлен. Вместо этого давайте подождем, пока токен не вернется и заголовок не будет установлен, прежде чем продолжить.

networkInterface.use([{
  applyMiddleware(req, next) {
    if(!req.options.headers) {
      req.options.headers = {}
    }
    AsyncStorage.getItem('token')
      .then(myToken => {
         req.options.headers.authorization = `Bearer ${myToken}`;
      })
      .then(next)  // call next() after authorization header is set.
      .catch(err => console.log(err));   
  }
}]);
Другие вопросы по тегам