swagger-api / swagger-api/swagger-codegen
[Swift] Access server-provided error response in AlamofireDecodableRequestBuilder
Nobody has claimed this yet.
- Dominant language
- Mustache
- Stars
- 17.8k
- Forks
- 6k
- PR merge metrics
- No merged PRs in 30d
Description
Description
Our API server returns a String error message that gives additional information as to why the request failed. A good example is when the user logs in using our API, the server returns either a userProfile object (successful login) or a user friendly error message as a String such as "Invalid password" which is better than just giving an Alamofire error code. Unfortunately, given the current implementation in AlamofireImplementations.swift, we are unable to access this message when the server's response is not a userProfile object as the swagger client expects for a successful response. However, Alamofire does receive the data object/response from the server—it just doesn't provide us an opportunity to use this response because it ignores the data received and just passes an Alamofire error to the API method.
Swagger-codegen version
swagger-codegen-cli-2.3.0-20171022.172748-209.jar
Suggest a fix/enhancement
The following fixes the solution for our specific implementation, and could help to guide in creating a solution overall, although we should ensure it works for everyone first. Our error responses are formatted as strings for example, but even still this should be backwards compatible if people are already successfully using it will the existing method implementation.
Changing the following code in AlamofireImplementations.swift:
guard dataResponse.result.isSuccess else {
completion(nil, ErrorResponse.Error(dataResponse.response?.statusCode ?? 500, dataResponse.data, dataResponse.result.error!))
return
}
to the following code will address the issue:
guard dataResponse.result.isSuccess else {
if let errorMessageData = dataResponse.data {
if let errorMessage = String(data: errorMessageData, encoding: String.Encoding.utf8) {
completion(nil, ErrorResponse.Error(dataResponse.response?.statusCode ?? 500, dataResponse.data, ErrorResponse.KnownError(errorMessage)))
}
}
else {
completion(nil, ErrorResponse.Error(dataResponse.response?.statusCode ?? 500, dataResponse.data,dataResponse.result.error!))
}
return
}
Additionally it's required to add the following case to the ErrorResponse enum in Models.swift:
public enum ErrorResponse : Error {
case Error(Int, Data?, Error)
case KnownError(String)
}
Note: For our specific issue it is resolved only changing it in the default case of T.self within func processRequest, but it's possible this also needs to be implemented in the other cases.
Another potential solution is to find where dataResponse.data is "lost" from the response, and instead include this as part of the error. This is probably a better solution, but could introduce non-backwards compatible changes.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in AlamofireImplementations.swift at processRequest, especially the default T.self case, and inspect Models.swift for ErrorResponse. Trace how dataResponse.data is handled for failed responses and compare the other request cases. Done means server-provided error data is accessible without breaking existing error handling across the generated Swift client.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- swift
- Domain
- api
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100