// // Network.swift // Werkout_ios // // Created by Trey Tartt on 6/19/23. // import Foundation enum FetchableError: Error { case apiError(Error) case noData case decodeError(Error) case endOfFileError case noPostData case statusError(Int, String?) } protocol Fetchable { associatedtype Response: Codable var baseURL: String { get } var endPoint: String { get } func fetch(completion: @escaping (Result) -> Void) } protocol Postable: Fetchable { var postableData: [String: Any]? { get } } extension Fetchable { var baseURL: String { "http://127.0.0.1:8000/" } func fetch(completion: @escaping (Result) -> Void) { let url = URL(string: baseURL+endPoint)! let task = URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) in if let error = error { completion(.failure(.apiError(error))) return } guard let data = data else { completion(.failure(.noData)) return } do { let model = try JSONDecoder().decode(Response.self, from: data) completion(.success(model)) return } catch { completion(.failure(.decodeError(error))) return } }) task.resume() } } extension Postable { func fetch(completion: @escaping (Result) -> Void) { guard let postableData = postableData else { completion(.failure(.noPostData)) return } let url = URL(string: baseURL+endPoint)! let postData = try! JSONSerialization.data(withJSONObject:postableData) var request = URLRequest(url: url,timeoutInterval: Double.infinity) request.addValue("Token fd59cbf6f5db98726e896cdb6b095ecb9c43a592", forHTTPHeaderField: "Authorization") request.addValue("application/json", forHTTPHeaderField: "Content-Type") request.httpMethod = "POST" request.httpBody = postData let task = URLSession.shared.dataTask(with: request, completionHandler: { data, response, error in if let error = error { completion(.failure(.apiError(error))) return } if let httpRespone = response as? HTTPURLResponse { if httpRespone.statusCode != 201 { var returnStr: String? if let data = data { returnStr = String(data: data, encoding: .utf8) } completion(.failure(.statusError(httpRespone.statusCode, returnStr))) return } } guard let data = data else { completion(.failure(.noData)) return } do { let model = try JSONDecoder().decode(Response.self, from: data) completion(.success(model)) return } catch { completion(.failure(.decodeError(error))) return } }) task.resume() } }