Alamofire retry doesn't work with validate()

1.5k views Asked by At

I started studying Swift and Alamofire. But I ran into a problem with RequestInterceptor: retry func doesn't work. My Request Interceptor:

class MyRequestInterceptor: RequestInterceptor {
    // MARK: - ADAPT
    func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
        print("-------ADAPT---------")
        var request = urlRequest
        guard let token = TokenService.getAccess() else {
            return
        }
        let bearerToken = "Bearer \(token)"
        request.setValue(bearerToken, forHTTPHeaderField: "Authorization")
        completion(.success(request))
    }
    
    // MARK: - RETRY
    func retry(_ request: Request, for session: Session, dueTo error: ApiError, completion: @escaping (RetryResult) -> Void) {
        print("--------RETRY-------")
        guard let refresh = TokenService.getRefresh() else {
            completion(.doNotRetry)
            return
        }
        let parameter = Refresh(token: refresh)
        AF.request(ApiManager.refresh.path, method: .post, parameters: parameter)
            .responseDecodable(of: TokensPair.self) { response in
                guard let tokens = response.value else {
                    completion(.doNotRetry)
                    return
                }
                TokenService.setAccess(token: tokens.access)
                TokenService.setRefresh(token: tokens.refresh)
                completion(.retry)
            }
    }
}

My Session Manager:

class SessionManager {
    static let shared = SessionManager()
    
    let sessionManager: Session = {
        let configuration = URLSessionConfiguration.af.default
        configuration.timeoutIntervalForRequest = 30
        configuration.waitsForConnectivity = true
        return Session(
            configuration: configuration,
            interceptor: MyRequestInterceptor()
        )
    }()
}

My request:

    func checkUser(complition: @escaping (Result<User, ApiError>) -> Void) {
        SessionManager.shared.sessionManager.request(ApiManager.me.path).validate().responseDecodable(of: User.self) {
            response in
            guard let user = response.value else {
                complition(.failure(.invalidCred))
                return
            }
            complition(.success(user))
        }
    }

Adapt work correctly. But retry never works. What am I doing wrong? I'm using validate() and expect the status code: 401 to cause an error that will cause a retry, but it doesn't work. I think problem in retry implementation. Because when i try replace

class MyRequestInterceptor: RequestInterceptor

to

class MyRequestInterceptor: RequestRetrier, RequestAdapter

I get error:

Type 'MyRequestInterceptor' does not conform to protocol 'RequestRetrier'

But i don't know why. And I didn't find solution.

I use: Xcode 13.2.1, Swift: 5, Alamofire: 5.4.4.

Thanks!

1

There are 1 answers

3
Jon Shier On BEST ANSWER

You used ApiError in the retry method signature, which breaks the conformance. It works with RequestInterceptor because that type provides a default implementation. Match the proper signature, ensure you have no local types shadowing the types in the signature, and it should work correctly.