Alamofire 5, как остановить все запросы, обновить токен доступа и перезапустить все остановленные запросы? - PullRequest
0 голосов
/ 01 октября 2019

Ситуацию, которую мне нужно исправить - представьте, что 2 запроса выполняются одновременно (когда токен доступа недействителен). Оба пытаются обновить токен, но один из них лишает законной силы токен для другого.

Есть ли способ как:

  1. разрешить только 1 обновлять токен
  2. остановить все остальные запросы
  3. перезапустить все остановленные запросы (при обновлении токена)

Или у вас есть идеи, как решить эту проблему другим способом?

Этотак выглядит мой запрос в каждом контроллере представления:

AF.request(encodedURLRequest, interceptor: AuthInterceptor()).validate().responseData { (response) in
    ...
}

Это мой AuthInterceptor:

final class AuthInterceptor: RequestInterceptor {

    func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
        var adaptedUrlRequest = urlRequest
        adaptedUrlRequest.setValue("Bearer \(UserDefaults.standard.getAccessToken())", forHTTPHeaderField: "Authorization")
        completion(.success(adaptedUrlRequest))
    }

    func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void) {
        print("request \(request) failed")
        if let response = request.task?.response as? HTTPURLResponse, response.statusCode == 403 {
            guard let url = URL(string: Endpoint.login.url) else { return }
            var urlRequest = URLRequest(url: url)
            urlRequest.httpMethod = "POST"
            urlRequest.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")

            let parameters: [String: String] = [
                "refresh_token": UserDefaults.standard.getRefreshToken(),
                "grant_type": "refresh_token"
            ]

            guard let encodedURLRequest = try? URLEncodedFormParameterEncoder.default.encode(parameters,
                                                                                             into: urlRequest) else { return }

            AF.request(encodedURLRequest).validate().responseData { (response) in
                if let data = response.data {
                    let decoder = JSONDecoder()
                    decoder.keyDecodingStrategy = .convertFromSnakeCase
                    if let loginResponse = try? decoder.decode(LoginResponse.self, from: data) {
                        UserDefaults.standard.setAccessToken(value: loginResponse.accessToken)
                        UserDefaults.standard.setRefreshToken(value: loginResponse.refreshToken)
                        completion(.retryWithDelay(1))
                    }
                }
            }
        }
    }

}

1 Ответ

0 голосов
/ 01 октября 2019

Вы можете использовать протокол Alamofire RequestRetrier (как часть протокола RequestInterceptor), чтобы делать это без необходимости вручную запускать и останавливать запросы.

По сути, вам необходимо знать, когда выполняется обновлениевыполнить и сохранить любые дополнительные обработчики завершения из запросов, которые не были выполнены из-за истекшего токена. Вы можете сделать это в вашем AuthInterceptor классе. Просто убедитесь, что ваша реализация потокобезопасна!

...