Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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. #2998

Closed
kst01 opened this issue Nov 14, 2019 · 13 comments

Comments

@kst01
Copy link

kst01 commented Nov 14, 2019

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

@kst01
Copy link
Author

kst01 commented Nov 14, 2019

`
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<T: Codable> (_ 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()
        }
    }

}

`

@99arobe
Copy link

99arobe commented Nov 14, 2019

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.

@kst01
Copy link
Author

kst01 commented Nov 14, 2019

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

@cnoon
Copy link
Member

cnoon commented Nov 14, 2019

@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.

@jshier
Copy link
Contributor

jshier commented Nov 14, 2019

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.

@cnoon
Copy link
Member

cnoon commented Nov 14, 2019

Thanks @jshier!

@kst01
Copy link
Author

kst01 commented Nov 15, 2019

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.

@jshier
Copy link
Contributor

jshier commented Nov 15, 2019

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

@kst01
Copy link
Author

kst01 commented Nov 15, 2019

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

Yes but not in same class.

@cnoon
Copy link
Member

cnoon commented Nov 15, 2019

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

@NikKovIos
Copy link

NikKovIos commented Dec 24, 2019

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.

@eddnav
Copy link

eddnav commented Aug 12, 2021

Adding to this, be careful of not putting your custom interceptor classes in extensions, that also does not work.

@baggednismo
Copy link

Adding more to this...

Make sure ALL parameters received by either of these functions are not overridden or explicitly disambiguate

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

func retry(_ request: Alamofire.Request, for session: Alamofire.Session, dueTo error: Swift.Error, completion: @escaping (RetryResult) -> Void) {}

In my case I used Error so I had to disambiguate with Swift.Error

My interceptor is going to remain this way just for accident sake.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants