Как заставить другие вызовы API эффективно ожидать обновления токена в перехватчике HTTP - PullRequest
0 голосов
/ 16 октября 2019

Я использую HttpInterceptor для добавления токена авторизации к каждому запросу API. Затем я подписываюсь на этот запрос, используя next.handle(newRequest).subscribe(...), и проверяю возвращенный результат / ошибку.

Когда запрос успешно выполняется, он просто передается. Но если этого не происходит, потому что токен авторизации недействителен, перехватчик обновляет токен авторизации и повторяет запрос. Если эта повторная попытка завершится неудачей, весь процесс завершится неудачно, как я намереваюсь.

Тогда проблема заключается в том, что несколько запросов могут и будут отправлены почти одновременно, что приводит к ситуации, когда более ранний запрос обнаруживает, чтоСрок действия токена истек и начинается процесс обновления токена. Затем - до того, как обновленный токен будет возвращен сервером - второй вызов отправляет запрос с истекшим токеном аутентификации, что приводит к другому обновлению, в результате чего первые обновленные «новые» полученные токены аутентификации становятся недействительными, и т. Д. Оба вызова будут выполнены успешноПовторите попытку, но это может привести к быстрому обновлению до 100 обновлений.

Вопросы

  1. Как отложить все запросы после первого, покапервый обновляет токен аутентификации, так что каждый последующий запрос использует недавно полученный токен аутентификации первых?

  2. Возможно ли использовать переменную-член, содержащую обещание, которое будет создано накаждое обновление, первым перехватывающим вызовом и какие другие вызовы ждут? Или может второй, почти одновременный вызов проскользнуть через создание обещания? Псевдокод для этого:

class Interceptor  implements HttpInterceptor
{
  private refreshPromise: Promise<void>;

  private authToken;

  intercept(req, next)
  {
    // ... subscribe for request with auth token added...
    observable.subscribe(
      result => // ... do something
      error => {
        //... if error because of token expiration

        if(this.refreshPromise)
          await this.refreshPromise;

        this.refreshPromise = new Promise((resolve, reject) => 
        {
          refreshToken().subscribe(
            result => { 
              this.authToken = result.token;
              resolve();
              this.refreshPromise = null;
            },
            error => // all is lost
          );
        });
      }
    );
    // ... request fails
  }
}

Я полагаю, это неосуществимо, потому что, когда я null the promise, те в очереди и не выполненные уже потерпят неудачу, или все, ожидающие обещание, будутперед нулевым уведомлением?!?

Альтернативный подход

Моя вторая идея состояла в том, чтобы иметь флаг переменной члена, который указывает, выполняется ли обновление или нет, и в случае, еслиэто означает, что запросы, переданные на эти вызовы intercept, будут добавлены в список отложенных запросов и будут выполнены первым перехватчиком после обновления.

Проблема с этим подходом заключается в обработке HttpRequests других вызовов на intercept по первому вызову на перехват. Поскольку цепочка от HttpClient до HttpBackend будет разорвана, и я не смогу вернуть результаты отложенных запросов в качестве результатов для первого.

Есть предложения или решения?

С уважением

...