I'm struggling to form a strongly-typed error object (the ApiErrorResponse object in my example below) from URLSession's .dataTaskPublisher(for:) publisher, but couldn't find a clue for that. Here I'm creating a class that fetches a joke object from a remote API and then I handle the result and error as follows (the class can be compiled as is in Xcode Playgrounds):
class DadJokes {
struct Joke: Codable {
let id: String
let joke: String
}
enum Error: Swift.Error {
case network
case parsing(apiResponse: ApiErrorResponse)
case unknown(urlResponse: URLResponse)
}
struct ApiErrorResponse: Codable {
let code: Int
let message: String
}
func getJoke(id: String) -> AnyPublisher<Joke, Error> {
let url = URL(string: "https://myJokes.com/\(id)")!
var request = URLRequest(url: url)
request.allHTTPHeaderFields = ["Accept": "application/json"]
return URLSession.shared
.dataTaskPublisher(for: request)
.map(\.data)
.decode(type: Joke.self, decoder: JSONDecoder())
.mapError { error -> DadJokes.Error in
switch error {
case is DecodingError:
//(1) <--- here I want to get the URLResponse.data from the upstream dataTaskPublisher to decode an object of type ApiErrorResponse (which is returned by the remote API) and pass it to the parsing error case
return .parsing(apiResponse: ApiErrorResponse(code: 1, message: "test"))
case is URLError:
return .network
default:
//(2) <---- here I want to get the URLResponse object that is emitted from the upstream dataTaskPublisher and pass it to the .unknown error case
// I need the URLResponse to read the underlying error info for debugging purposes
return .unknown(urlResponse: URLResponse())
}
}
.eraseToAnyPublisher()
}
}
I have three questions, two of them are commented in the code above. The third one is: what should I do in order to return a never failing publisher from getJoke function ? i.e. I need the return type of the function to be AnyPublisher<Result<Joke, Error>, Never>