Marcus Leon
Marcus Leon

Reputation: 56669

Alamofire: Network error vs invalid status code?

Using Alamofire 4/Swift 3 how can you differentiate between a request that fails due to:

  1. Network connectivity (host down, can't reach host) vs
  2. Invalid server HTTP response code (ie: 499) which causes the Alamofire request to fail due to calling validate()?

Code:

    sessionManager.request(url, method: .post, parameters:dict, encoding: JSONEncoding.default)
        .validate() //Validate status code
        .responseData { response in

        if response.result.isFailure {
               //??NETWORK ERROR OR INVALID SERVER RESPONSE??
        }
    }

We want to handle each case differently. In the latter case we want to interrogate the response. (In the former we don't as there is no response).

Upvotes: 8

Views: 7214

Answers (3)

Marcus Leon
Marcus Leon

Reputation: 56669

Here's our current working solution:

sessionManager.request(url, method: .post, parameters:dict, encoding: JSONEncoding.default)
    .validate() //Validate status code
    .responseData { response in

    if response.result.isFailure {
        if let error = response.result.error as? AFError, error.responseCode == 499 {
            //INVALID SESSION RESPONSE
        } else {
            //NETWORK FAILURE
        }
    }
}

If result.error it is of type AFError you can use responseCode. From the AFError source comments:

/// Returns whether the `AFError` is a response validation error. When `true`, the `acceptableContentTypes`,
/// `responseContentType`, and `responseCode` properties will contain the associated values.
public var isResponseValidationError: Bool {
    if case .responseValidationFailed = self { return true }
    return false
}

Maybe there is a better way (?) but that seems to work...

Upvotes: 4

Hamish
Hamish

Reputation: 1745

Alamofire can tell you about the status of the request, this code works just fine for me:

if let error = response.result.error as? NSError {
    print(error)//print the error description
    if (error.code == -1009){
                    print(error.code) // this will print -1009,somehow it means , there is no internet connection
                    self.errorCode = error.code

    }
      //check for other error.code    

}else{
  //there is no problem
}

the error.code will tell you what is the problem

Upvotes: 2

Alessandro Ornano
Alessandro Ornano

Reputation: 35392

Automatic validation should consider status code within 200...299 (success codes) range so when you get an invalid server HTTP response code 5xx (499 means Client Closed Request) you are sure it's not depend by validation.

About the statusCode, my advice is to follow the correct new rules to get it. If you have some problem to retrieve it look this SO answer.

Speaking about network reachability you could write:

let manager = NetworkReachabilityManager(host: "www.apple.com")
manager?.listener = { status in
    print("Network Status Changed: \(status)")
}
manager?.startListening()

There are some important things to remember when using network reachability to determine what to do next.

  • Do NOT use Reachability to determine if a network request should be sent. You should ALWAYS send it.
  • When Reachability is restored, use the event to retry failed network requests. Even though the network requests may still fail, this is a good moment to retry them.
  • The network reachability status can be useful for determining why a network request may have failed. If a network request fails, it is more useful to tell the user that the network request failed due to being offline rather than a more technical error, such as "request timed out."

You can find these details also in the official Alamofire 4 GitHUB page

Upvotes: 1

Related Questions