mirror of
https://github.com/saymrwulf/puncture.git
synced 2026-06-20 02:07:59 +00:00
70 lines
2.8 KiB
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
|
|
}
|
|
}
|