Using retryWhen to update tokens based on http error code : <p>I found this example on <a href="http://sapandiwakar.in/refresh-oauth-tokens-using-moya-rxswift/" rel="noreferrer">How to refresh oauth token using moya and rxswift</a> which I had to alter slightly to get to compile. This code works 80% for my scenario. The problem with it is that it will run for all http errors, and not just 401 errors. What I want is to have all my other http errors passed on as errors, so that I can handle them else where and not swallow them here.</p>

<p>With this code, if I get a <code>HttpStatus 500</code>, it will run the authentication code 3 times which is obviously not what I want.</p>

<p>Ive tried to alter this code to handle only handle <code>401</code> errors, but it seem that no matter what I do I can't get the code to compile. It's always complaining about wrong return type, <code>"Cannot convert return expression of type Observable&lt;Response&gt; to return type Observable&lt;Response&gt;"</code> which makes no sense to me..</p>

<p>What I want: handle 401, but stop on all other errors</p>

<pre><code>import RxSwift
import KeychainAccess
import Moya

public extension ObservableType where E == Response {

  /// Tries to refresh auth token on 401 errors and retry the request.
  /// If the refresh fails, the signal errors.
  public func retryWithAuthIfNeeded() -&gt; Observable&lt;E&gt; {
    return self.retryWhen {
      (e: Observable&lt;ErrorType&gt;) in
      return Observable.zip(e, Observable.range(start: 1, count: 3), resultSelector: { $1 })
        .flatMap { i in
          return AuthProvider.sharedInstance.request(
            .LoginFacebookUser(
              accessToken: AuthenticationManager.defaultInstance().getLoginTokenFromKeyChain(),
              useFaceBookLogin: AuthenticationManager.defaultInstance().isFacebookLogin())
            )
            .filterSuccessfulStatusCodes()
            .mapObject(Accesstoken.self)
            .catchError {
              error in
              log.debug("ReAuth error: \(error)")
              if case Error.StatusCode(let response) = error {
                if response.statusCode == 401 {
                  // Force logout after failed attempt
                  log.debug("401:, force user logout")
                  NSNotificationCenter.defaultCenter().postNotificationName(Constants.Notifications.userNotAuthenticated, object: nil, userInfo: nil)
                }
              }
              return Observable.error(error)
            }.flatMapLatest({
              token -&gt; Observable&lt;Accesstoken&gt; in
              AuthenticationManager.defaultInstance().storeServiceTokenInKeychain(token)
              return Observable.just(token)
            })
      }
    }
  }
}
</code></pre>
