Hi I have just jumped on-board to Moya. I've checked out the basic walkthrough and have set up my API swift file.
I noticed that the failure case doesn't handle all errors.
What is your recommended approach to handling more error status code from my server (ie. 400, 401, 403, 404, 500)?
P.S. Sample project would be wonderful!
Hope to learn and contribute!
Thanks.
Hey @nhantrivinh,
There is a method on Moya response which you can use to filter a specific status code:
public func filter(statusCode: Int) throws -> Response
Let me know if this helps.
Hi @SD10 ,
Thank you for your reply!
The following was what I was looking for:
do {
try moyaResponse.filterSuccessfulStatusCodes()
let data = try moyaResponse.mapJSON()
}
catch {
// show an error to your user
}
I am not sure about the recommended approach for error catching in this case.
I want to print out the error description but the error object doesn't contain an error description property.
I.e:
Error = 401
Error Description = "Unauthorized – You are not authorized to this action"
My server returns me something like this which falls into the error in the catch:
{
"errors": [
{
"status": 401,
"title": "A confirmation email was sent to your account at '%{email}'. You must follow the instructions in the email before your account can be activated",
"detail": "",
"source": ""
}
]
}
Any recommended approach for printing out error description would be great!
Thanks.
The approach is up to you :)
If you want to catch the error, then maybe want to push a uialercontroller onto the view hierarchy?
Another option could be to try re-trying the request
@AndrewSB Thanks for your response!
However, it isn't exactly what I was looking for.
The problem I am facing from using:
do {
try moyaResponse.filterSuccessfulStatusCodes()
let data = try moyaResponse.mapJSON()
print(data)
} catch {
print(error)
}
Is that the error caught does not contain the error description.
The catching of the error prints something like this:
statusCode(Status Code: 401, Data Length: 106)
I then try to retrieve the JSON from moyaResponse.data.
However, it only gave me:
statusCode(Status Code: 401, Data Length: 106)
When I was expecting the following to return (from testing with Postman):
{
"errors": [
{
"status": 401,
"title": "A confirmation email was sent to your account at '%{email}'. You must follow the instructions in the email before your account can be activated",
"detail": "",
"source": ""
}
]
}
This way, I can get the error message from the title key and do something with it.
Basically, I want is to get the JSON to get the error message.
UPDATE
Turned out this was what I was looking for:
switch result {
case let .success(moyaResponse):
do {
try moyaResponse.filterSuccessfulStatusCodes()
let data = try moyaResponse.mapJSON()
} catch {
if let error = error as? MoyaError {
do {
let body = try error.response?.mapJSON()
} catch {
print(error)
}
}
}
case let .failure(error):
// TODO: handle the error == best. comment. ever.
break
}
It isn't the cleanest, but the body was what I was looking for :)
Thank you @SD10 and @AndrewSB for your help!
@nhantrivinh Glad you were able to work this out 😃
Is there a reason why 401, 403's etc no longer return a an .failure(error) when making an api call? That seems to me like what would be expected but looking at:
public func convertResponseToResult(_ response: HTTPURLResponse?, request: URLRequest?, data: Data?, error: Swift.Error?) ->
Result<Moya.Response, MoyaError> {
switch (response, data, error) {
case let (.some(response), data, .none):
let response = Moya.Response(statusCode: response.statusCode, data: data ?? Data(), request: request, response: response)
return .success(response)
case let (.some(response), _, .some(error)):
let response = Moya.Response(statusCode: response.statusCode, data: data ?? Data(), request: request, response: response)
let error = MoyaError.underlying(error, response)
return .failure(error)
case let (_, _, .some(error)):
let error = MoyaError.underlying(error, nil)
return .failure(error)
default:
let error = MoyaError.underlying(NSError(domain: NSURLErrorDomain, code: NSURLErrorUnknown, userInfo: nil), nil)
return .failure(error)
}
}
.failure(error) wont be returned unless convertResponseToResult is passed an error for the error param which alamoFire (which is called for making the api call by Moya) doesn't return in the case of 403's for example.
Most helpful comment
UPDATE
Turned out this was what I was looking for:
It isn't the cleanest, but the body was what I was looking for :)
Thank you @SD10 and @AndrewSB for your help!