111 lines
3.6 KiB
Swift
111 lines
3.6 KiB
Swift
// Copyright © 2025 VOID Software SA. All rights reserved.
|
|
|
|
import Foundation
|
|
|
|
/// Custom error types for API operations
|
|
enum APIError: Error, LocalizedError, Equatable {
|
|
case invalidURL
|
|
case noData
|
|
case decodingFailed(Error)
|
|
case encodingFailed(Error)
|
|
case unauthorized
|
|
case forbidden
|
|
case notFound
|
|
case serverError(statusCode: Int)
|
|
case networkError(Error)
|
|
case unexpectedResponse
|
|
case timeout
|
|
case cancelled
|
|
case custom(String)
|
|
|
|
var errorDescription: String? {
|
|
switch self {
|
|
case .invalidURL:
|
|
return "Invalid URL"
|
|
case .noData:
|
|
return "No data received from server"
|
|
case .decodingFailed(let error):
|
|
return "Failed to decode response: \(error.localizedDescription)"
|
|
case .encodingFailed(let error):
|
|
return "Failed to encode parameters: \(error.localizedDescription)"
|
|
case .unauthorized:
|
|
return "Unauthorized. Please login again."
|
|
case .forbidden:
|
|
return "Access forbidden"
|
|
case .notFound:
|
|
return "Resource not found"
|
|
case .serverError(let statusCode):
|
|
return "Server error (Status: \(statusCode))"
|
|
case .networkError(let error):
|
|
return "Network error: \(error.localizedDescription)"
|
|
case .unexpectedResponse:
|
|
return "Unexpected response from server"
|
|
case .timeout:
|
|
return "Request timeout"
|
|
case .cancelled:
|
|
return "Request cancelled"
|
|
case .custom(let message):
|
|
return message
|
|
}
|
|
}
|
|
|
|
static func == (lhs: APIError, rhs: APIError) -> Bool {
|
|
switch (lhs, rhs) {
|
|
case (.invalidURL, .invalidURL),
|
|
(.noData, .noData),
|
|
(.unauthorized, .unauthorized),
|
|
(.forbidden, .forbidden),
|
|
(.notFound, .notFound),
|
|
(.unexpectedResponse, .unexpectedResponse),
|
|
(.timeout, .timeout),
|
|
(.cancelled, .cancelled):
|
|
return true
|
|
case (.serverError(let lhsCode), .serverError(let rhsCode)):
|
|
return lhsCode == rhsCode
|
|
case (.custom(let lhsMessage), .custom(let rhsMessage)):
|
|
return lhsMessage == rhsMessage
|
|
case (.decodingFailed(let lhsError), .decodingFailed(let rhsError)):
|
|
return lhsError.localizedDescription == rhsError.localizedDescription
|
|
case (.encodingFailed(let lhsError), .encodingFailed(let rhsError)):
|
|
return lhsError.localizedDescription == rhsError.localizedDescription
|
|
case (.networkError(let lhsError), .networkError(let rhsError)):
|
|
return lhsError.localizedDescription == rhsError.localizedDescription
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Detailed server error with request/response information
|
|
struct ServerError: Error, LocalizedError {
|
|
let statusCode: Int?
|
|
let message: String?
|
|
let data: Data?
|
|
let request: URLRequest?
|
|
let response: HTTPURLResponse?
|
|
|
|
var errorDescription: String? {
|
|
if let message = message {
|
|
return message
|
|
}
|
|
if let statusCode = statusCode {
|
|
return "Server error: \(statusCode)"
|
|
}
|
|
return "Unknown server error"
|
|
}
|
|
|
|
init(
|
|
statusCode: Int? = nil,
|
|
message: String? = nil,
|
|
data: Data? = nil,
|
|
request: URLRequest? = nil,
|
|
response: HTTPURLResponse? = nil
|
|
) {
|
|
self.statusCode = statusCode
|
|
self.message = message
|
|
self.data = data
|
|
self.request = request
|
|
self.response = response
|
|
}
|
|
}
|