Alamofire 5.0.0-rc.3 RequestInterceptor Adapt method not being called of Alamofire although retry gets called when there is any error in response.

Created on 14 Nov 2019  路  11Comments  路  Source: Alamofire/Alamofire

What did you do?

Created a class conforming to RequestInterceptor protocol and implemented adapt & retry delegate methods.

What did you expect to happen?

Adapt method to get called where in i can add tokens to request headers.

What happened instead?

adapt method didnt get called, although retry gets called in case there is an error in the response.

Alamofire Environment

Alamofire version: Alamofire 5.0.0-rc.3
Xcode version: 11.0
Swift version: 5.0
Platform(s) running Alamofire: iOS
macOS version running Xcode: 10.14.6

Archive.zip

request adapter support

Most helpful comment

I've experienced runtime issues with this method before, when it was being called from a file which imported an additional Result type. In that case, PromiseKit's. Attempts to disambiguate using Swift.Result didn't work, the method just wasn't being called at runtime. What finally worked was using a typealias to do the disambiguation and then using it in the method.

typealias AdapterResult = Swift.Result<URLRequest, Error>

... in adapter ...

func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (AdapterResult) -> Void) { }

This may be fixed in newer Swift compilers but I thought I'd mention it just in case.

All 11 comments

`
class Interceptor: RequestInterceptor {

  func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (AFResult<URLRequest>) -> Void) {
       print("ADAPT :=")
       completion(.success(urlRequest))
   }

   func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void) {
       print("RETRY :=")
       completion(.doNotRetry)

   }

}
`

`
public func request (_ urlConvertible: URLRequestConvertible) -> Observable {
return Observable.create { observer in

        // 1
        print("Url := \(urlConvertible.urlRequest!.url!)")

        // 2
        let request = AF.request(urlConvertible, interceptor: Interceptor()).responseDecodable { (response: AFDataResponse<T>) in

            if let data = response.data{
                print("Response := \(String(decoding: data, as: UTF8.self))")
            }
            else{
                print("data is nil")
            }

            switch response.result {
            case .success(let value):
                print("value :-> \(value)")
                observer.onNext(value)
                observer.onCompleted()
            case .failure(let error):

                observer.onError(error)
            }
        }

        //Finally, we return a disposable to stop the request
        return Disposables.create {
            request.cancel()
        }
    }

}

`

Might be worth checking the method signature of your adapt method.

I think it should be:
func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void)

whereas your method is:
fun adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (AFResult<URLRequest>) -> Void)

I believe AFResult<URLRequest> was changed using a typealias in commit 6a75f4f.

Might be worth checking the method signature of your adapt method.

I think it should be:
func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void)

whereas your method is:
fun adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (AFResult<URLRequest>) -> Void)

I believe AFResult<URLRequest> was changed using a typealias in commit 6a75f4f.

Tried with that method as well still not getting called

@kst01 it has to be that your method signature is incorrect. There's default implementations for RequestAdapter and RequestRetrier built into RequestInterceptor extensions. If the API you have for adapt isn't exactly right, it won't be called. You can put a breakpoint here during execution to verify what's actually being called.

I've experienced runtime issues with this method before, when it was being called from a file which imported an additional Result type. In that case, PromiseKit's. Attempts to disambiguate using Swift.Result didn't work, the method just wasn't being called at runtime. What finally worked was using a typealias to do the disambiguation and then using it in the method.

typealias AdapterResult = Swift.Result<URLRequest, Error>

... in adapter ...

func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (AdapterResult) -> Void) { }

This may be fixed in newer Swift compilers but I thought I'd mention it just in case.

Thanks @jshier!

I've experienced runtime issues with this method before, when it was being called from a file which imported an additional Result type. In that case, PromiseKit's. Attempts to disambiguate using Swift.Result didn't work, the method just wasn't being called at runtime. What finally worked was using a typealias to do the disambiguation and then using it in the method.

typealias AdapterResult = Swift.Result<URLRequest, Error>

... in adapter ...

func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (AdapterResult) -> Void) { }

This may be fixed in newer Swift compilers but I thought I'd mention it just in case.

Thanks soo much jshier, this is what was causing the issue. Thanks a lot for the fix as well.

@kst01 Out of curiosity, did you have another Result type too?

@kst01 Out of curiosity, did you have another Result type too?

Yes but not in same class.

Thanks for documenting everything in this issue @jshier and @kst01! 馃嵒 Hopefully this helps others that run into the same ambiguity issues.

I using

func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Swift.Result<URLRequest, Error>) -> Void) {

(Added Swift. to Result) And adapter works well with this.

Was this page helpful?
0 / 5 - 0 ratings