puncture/goapp/ios/EmergencyPuncture/Sources/APIClient.swift

70 lines
2.8 KiB
Swift

import Foundation
enum APIError: Error, LocalizedError {
case invalidURL
case badStatus(Int)
case backend(String)
var errorDescription: String? {
switch self {
case .invalidURL: return "Invalid URL"
case .badStatus(let code): return "HTTP \(code)"
case .backend(let message): return message
}
}
}
@MainActor
final class APIClient {
func loadProviders(masterURL: String, token: String) async throws -> [ProviderLite] {
guard let url = URL(string: masterURL.trimmingCharacters(in: .whitespacesAndNewlines) + "/api/live/state") else {
throw APIError.invalidURL
}
var req = URLRequest(url: url)
req.httpMethod = "GET"
if !token.isEmpty {
req.addValue(token, forHTTPHeaderField: "X-Puncture-Token")
}
let (data, resp) = try await URLSession.shared.data(for: req)
guard let http = resp as? HTTPURLResponse else { throw APIError.badStatus(-1) }
guard (200...299).contains(http.statusCode) else { throw APIError.badStatus(http.statusCode) }
if let top = try? JSONDecoder().decode([String: [ProviderLite]].self, from: data), let providers = top["providers"] {
return providers
}
if let payload = try? JSONDecoder().decode(LiveStatePayload.self, from: data) {
if let providers = payload.providers {
return providers
}
if let state = payload.state {
return state.providers
}
}
return []
}
func punctureProvider(masterURL: String, providerID: Int, token: String) async throws -> RemotePunctureResponse {
guard let url = URL(string: masterURL.trimmingCharacters(in: .whitespacesAndNewlines) + "/api/remote/puncture-provider") else {
throw APIError.invalidURL
}
var req = URLRequest(url: url)
req.httpMethod = "POST"
req.addValue("application/json", forHTTPHeaderField: "Content-Type")
if !token.isEmpty {
req.addValue(token, forHTTPHeaderField: "X-Puncture-Token")
}
req.httpBody = try JSONEncoder().encode(RemotePunctureRequest(provider_id: providerID))
let (data, resp) = try await URLSession.shared.data(for: req)
guard let http = resp as? HTTPURLResponse else { throw APIError.badStatus(-1) }
let decoded = (try? JSONDecoder().decode(RemotePunctureResponse.self, from: data)) ?? RemotePunctureResponse(ok: false, error: "Invalid response", provider_id: nil)
guard (200...299).contains(http.statusCode) else {
throw APIError.backend(decoded.error ?? "HTTP \(http.statusCode)")
}
if !decoded.ok {
throw APIError.backend(decoded.error ?? "Puncture rejected")
}
return decoded
}
}