144 lines
4.2 KiB
Swift
144 lines
4.2 KiB
Swift
//
|
|
// Network.swift
|
|
// Werkout_ios
|
|
//
|
|
// Created by Trey Tartt on 6/19/23.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
enum BaseURLs: String {
|
|
case local = "http://127.0.0.1:8000"
|
|
case dev = "https://dev.werkout.fitness"
|
|
}
|
|
|
|
enum FetchableError: Error {
|
|
case apiError(Error)
|
|
case noData
|
|
case decodeError(Error)
|
|
case endOfFileError
|
|
case noPostData
|
|
case noToken
|
|
case statusError(Int, String?)
|
|
}
|
|
|
|
protocol Fetchable {
|
|
associatedtype Response: Codable
|
|
var attachToken: Bool { get }
|
|
var baseURL: String { get }
|
|
var endPoint: String { get }
|
|
func fetch(completion: @escaping (Result<Response, FetchableError>) -> Void)
|
|
}
|
|
|
|
protocol Postable: Fetchable {
|
|
var postableData: [String: Any]? { get }
|
|
var successStatus: Int { get }
|
|
}
|
|
|
|
extension Fetchable {
|
|
var baseURL: String {
|
|
BaseURLs.local.rawValue
|
|
}
|
|
|
|
var attachToken: Bool {
|
|
return true
|
|
}
|
|
|
|
func fetch(completion: @escaping (Result<Response, FetchableError>) -> Void) {
|
|
let url = URL(string: baseURL+endPoint)!
|
|
|
|
var request = URLRequest(url: url,timeoutInterval: Double.infinity)
|
|
if attachToken {
|
|
guard let token = UserStore.shared.token else {
|
|
completion(.failure(.noPostData))
|
|
return
|
|
}
|
|
request.addValue(token, forHTTPHeaderField: "Authorization")
|
|
}
|
|
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
|
|
|
|
let task = URLSession.shared.dataTask(with: request, 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<Response, FetchableError>) -> 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)
|
|
if attachToken {
|
|
guard let token = UserStore.shared.token else {
|
|
completion(.failure(.noPostData))
|
|
return
|
|
}
|
|
request.addValue(token, 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 != successStatus {
|
|
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()
|
|
}
|
|
}
|