38 lines
1.1 KiB
Swift
38 lines
1.1 KiB
Swift
import Foundation
|
||
|
||
/// 网络错误。
|
||
public enum NetworkError: Error, Sendable {
|
||
case invalidResponse
|
||
case http(statusCode: Int)
|
||
case decoding(String)
|
||
}
|
||
|
||
/// 通用 HTTP 客户端(对应 Android Retrofit 的最小抽象)。
|
||
public protocol APIClient: Sendable {
|
||
func get<T: Decodable & Sendable>(_ url: URL) async throws -> T
|
||
}
|
||
|
||
/// 基于 URLSession 的 APIClient 实现。
|
||
public struct URLSessionAPIClient: APIClient {
|
||
private let session: URLSession
|
||
|
||
public init(session: URLSession = .shared) {
|
||
self.session = session
|
||
}
|
||
|
||
public func get<T: Decodable & Sendable>(_ url: URL) async throws -> T {
|
||
let (data, response) = try await session.data(from: url)
|
||
guard let http = response as? HTTPURLResponse else {
|
||
throw NetworkError.invalidResponse
|
||
}
|
||
guard (200..<300).contains(http.statusCode) else {
|
||
throw NetworkError.http(statusCode: http.statusCode)
|
||
}
|
||
do {
|
||
return try JSONDecoder().decode(T.self, from: data)
|
||
} catch {
|
||
throw NetworkError.decoding(error.localizedDescription)
|
||
}
|
||
}
|
||
}
|