89 lines
2.3 KiB
Swift
89 lines
2.3 KiB
Swift
//
|
|
// Utilities.swift
|
|
// QueueCube
|
|
//
|
|
// Created by James Magahern on 3/3/25.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
extension Optional
|
|
{
|
|
func try_unwrap() throws -> Wrapped {
|
|
guard let self else { throw UnwrapError() }
|
|
return self
|
|
}
|
|
|
|
struct UnwrapError: Swift.Error {}
|
|
}
|
|
|
|
struct RequestBuilder
|
|
{
|
|
let url: URL
|
|
private var httpMethod: HTTPMethod = .get
|
|
private var body: Data? = nil
|
|
|
|
init(url: URL) {
|
|
self.url = url
|
|
}
|
|
|
|
public func method(_ method: HTTPMethod) -> Self {
|
|
var copy = self
|
|
copy.httpMethod = method
|
|
return copy
|
|
}
|
|
|
|
public func path(_ path: any StringProtocol) -> Self {
|
|
return RequestBuilder(url: self.url.appending(path: path))
|
|
}
|
|
|
|
public func body(_ data: Codable) -> Self {
|
|
var copy = self
|
|
copy.body = try! JSONEncoder().encode(data)
|
|
return copy
|
|
}
|
|
|
|
public func build() -> URLRequest {
|
|
var request = URLRequest(url: self.url)
|
|
request.httpMethod = self.httpMethod.rawValue
|
|
if let body {
|
|
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
|
|
request.httpBody = body
|
|
}
|
|
|
|
return request
|
|
}
|
|
|
|
public func json<T: Decodable>() async throws -> T {
|
|
let urlRequest = self.build()
|
|
let (data, _) = try await URLSession.shared.data(for: urlRequest)
|
|
return try JSONDecoder().decode(T.self, from: data)
|
|
}
|
|
|
|
public func post() async throws {
|
|
try await self.method(.post).execute()
|
|
}
|
|
|
|
public func execute() async throws {
|
|
let urlRequest = self.build()
|
|
let (data, response) = try await URLSession.shared.data(for: urlRequest)
|
|
if let httpResponse = response as? HTTPURLResponse {
|
|
if httpResponse.statusCode != 200 {
|
|
print("POST error \(httpResponse.statusCode): \(String(data: data, encoding: .utf8)!)")
|
|
}
|
|
}
|
|
}
|
|
|
|
public func websocket() -> URL {
|
|
guard var components = URLComponents(url: self.url, resolvingAgainstBaseURL: false) else { fatalError() }
|
|
components.scheme = components.scheme == "https" ? "wss" : "ws"
|
|
return components.url!
|
|
}
|
|
|
|
enum HTTPMethod: String {
|
|
case get = "GET"
|
|
case post = "POST"
|
|
case delete = "DELETE"
|
|
}
|
|
}
|