Search code examples
alamofire

Decoding an Error Response using Alamofire 5 and the responseDecodable function


I'm writing an API Client for WooCommerce using Alamofire 5 (beta 1) which will allow me to get orders, coupons etc as well as create them. Note I am using the new .responseDecodable function.

I've set up my API client using the following performRequest function that looks like this:

@discardableResult
private static func performRequest<T:Decodable>(route: APIConfiguration,
                                                decoder: JSONDecoder = JSONDecoder(),
                                                completion: @escaping (Result<T>)->Void) -> DataRequest {
    return AF.request(route)
        .responseDecodable(decoder: decoder) { (response: DataResponse<T>) in
            completion(response.result)
    }
}

This works well, since I can, for instance, call a function getCouponForId(_ id: Int) which will execute this function and have the response returned through the completion handler.

The only downfall is that, say the user tries to access a coupon that does not exist, they will receive an error (404 from the server). I can switch on the result to determine either a success or failure case, but Alamofire attempts to decode the body of the error response into the Coupon model I have created.

Going forward, I have created an error model which I intend to have the error decoded using. But with that said, I'm having trouble implementing it into this function.

Does anyone have any ideas on how I could handle this?

(I have created this function through following this guide - hopefully, it might provide a bit more context to what I'm doing. https://github.com/AladinWay/NetworkingExample)


Solution

  • Similiar login function from the article you mentioned, updated for current beta of Alamofire 5 and dealing with 404, 401 etc. (via the guard statement)

      static func login(email: String, password: String, completion:@escaping (Result<UserCredentials>)->Void) {
        performRequest(router: Router.login(email: email, password: password), completion: completion)
        AF.request(Router.login(email: email, password: password))
          .validate(statusCode: 200..<300)
          .responseDecodable { (response: DataResponse<UserCredentials>) in
            guard response.result.isSuccess else {
              print("🥶 Error on login: \(String(describing: response.error))")
              return
            }
            completion(response.result)
        }
      }