Files
hope-voice-api/Sources/Networking/ServerConfig.swift
T
snowspeeder 378b8cb36f feat: server config, token client, TLS pinning, connection test (Phase 1)
ServerConfig parses https base URL and derives wss livekit URL;
TokenClient POSTs /token with clean 503/offline error states;
TLSPinning holds optional cert SHA-384 pins (empty = system trust);
Settings gains a Connection test screen proving the endpoint works.
2026-08-29 17:18:38 -04:00

43 lines
1.5 KiB
Swift

import Foundation
struct ServerConfig: Equatable {
let baseURL: URL
let livekitURL: URL
enum ConfigError: LocalizedError, Equatable {
case notHTTPS(String)
case invalidURL(String)
var errorDescription: String? {
switch self {
case .notHTTPS(let raw):
return "Server URL must use https: \(raw)"
case .invalidURL(let raw):
return "Invalid server URL: \(raw)"
}
}
}
static func parse(_ raw: String) -> Result<ServerConfig, ConfigError> {
let trimmed = raw.trimmingCharacters(in: .whitespacesAndNewlines)
guard !trimmed.isEmpty else { return .failure(.invalidURL(raw)) }
var candidate = trimmed
if !candidate.contains("://") { candidate = "https://" + candidate }
guard let components = URLComponents(string: candidate),
let scheme = components.scheme?.lowercased(),
let host = components.host, !host.isEmpty else {
return .failure(.invalidURL(raw))
}
if scheme != "https" { return .failure(.notHTTPS(raw)) }
var c = components
c.path = ""
c.fragment = nil
guard let base = c.url else { return .failure(.invalidURL(raw)) }
let portSuffix = components.port.map { ":\($0)" } ?? ""
let livekit = URL(string: "wss://\(host)\(portSuffix)/livekit")!
return .success(ServerConfig(baseURL: base, livekitURL: livekit))
}
var host: String { baseURL.host ?? "" }
}