|
|
|
|
@ -7,7 +7,7 @@ |
|
|
|
|
|
|
|
|
|
import Foundation |
|
|
|
|
|
|
|
|
|
enum Method: String { |
|
|
|
|
public enum HTTPMethod: String, CaseIterable { |
|
|
|
|
case get = "GET" |
|
|
|
|
case post = "POST" |
|
|
|
|
case put = "PUT" |
|
|
|
|
@ -27,7 +27,7 @@ fileprivate enum ServiceConf: String { |
|
|
|
|
case getUser = "plus/user-by-token/" |
|
|
|
|
case changePassword = "plus/change-password/" |
|
|
|
|
|
|
|
|
|
var method: Method { |
|
|
|
|
var method: HTTPMethod { |
|
|
|
|
switch self { |
|
|
|
|
case .createAccount, .requestToken: |
|
|
|
|
return .post |
|
|
|
|
@ -86,7 +86,7 @@ public class Services { |
|
|
|
|
return try await _runRequest(request, apiCallId: apiCallId) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fileprivate func _runRequest<T: Encodable, U: Decodable>(servicePath: String, method: Method, payload: T, apiCallId: String? = nil) async throws -> U { |
|
|
|
|
fileprivate func _runRequest<T: Encodable, U: Decodable>(servicePath: String, method: HTTPMethod, payload: T, apiCallId: String? = nil) async throws -> U { |
|
|
|
|
var request = try self._baseRequest(servicePath: servicePath, method: method) |
|
|
|
|
request.httpBody = try jsonEncoder.encode(payload) |
|
|
|
|
return try await _runRequest(request, apiCallId: apiCallId) |
|
|
|
|
@ -124,24 +124,41 @@ public class Services { |
|
|
|
|
} |
|
|
|
|
return try jsonDecoder.decode(T.self, from: task.0) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fileprivate func _postRequest(servicePath: String, requiresToken: Bool? = nil) throws -> URLRequest { |
|
|
|
|
return try self._baseRequest(servicePath: servicePath, method: .post, requiresToken: requiresToken) |
|
|
|
|
|
|
|
|
|
fileprivate func _isTokenRequired<T : Storable>(type: T.Type, method: HTTPMethod) -> Bool { |
|
|
|
|
let methods = T.tokenExemptedMethods() |
|
|
|
|
if methods.contains(method) { |
|
|
|
|
return false |
|
|
|
|
} else { |
|
|
|
|
return true |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fileprivate func _getRequest<T: Storable>(type: T.Type) throws -> URLRequest { |
|
|
|
|
let requiresToken = self._isTokenRequired(type: T.self, method: .get) |
|
|
|
|
return try self._baseRequest(servicePath: T.path(), method: .get, requiresToken: requiresToken) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fileprivate func _postRequest<T: Storable>(type: T.Type) throws -> URLRequest { |
|
|
|
|
let requiresToken = self._isTokenRequired(type: T.self, method: .post) |
|
|
|
|
return try self._baseRequest(servicePath: T.path(), method: .post, requiresToken: requiresToken) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fileprivate func _putRequest(servicePath: String, requiresToken: Bool? = nil) throws -> URLRequest { |
|
|
|
|
return try self._baseRequest(servicePath: servicePath, method: .put, requiresToken: requiresToken) |
|
|
|
|
fileprivate func _putRequest<T: Storable>(type: T.Type, id: String) throws -> URLRequest { |
|
|
|
|
let requiresToken = self._isTokenRequired(type: T.self, method: .put) |
|
|
|
|
return try self._baseRequest(servicePath: T.path(id: id), method: .put, requiresToken: requiresToken) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fileprivate func _getRequest(servicePath: String, requiresToken: Bool? = nil) throws -> URLRequest { |
|
|
|
|
return try self._baseRequest(servicePath: servicePath, method: .get, requiresToken: requiresToken) |
|
|
|
|
fileprivate func _deleteRequest<T: Storable>(type: T.Type, id: String) throws -> URLRequest { |
|
|
|
|
let requiresToken = self._isTokenRequired(type: T.self, method: .delete) |
|
|
|
|
return try self._baseRequest(servicePath: T.path(id: id), method: .delete, requiresToken: requiresToken) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fileprivate func _baseRequest(conf: ServiceConf) throws -> URLRequest { |
|
|
|
|
return try self._baseRequest(servicePath: conf.rawValue, method: conf.method, requiresToken: conf.requiresToken) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fileprivate func _baseRequest(servicePath: String, method: Method, requiresToken: Bool? = nil) throws -> URLRequest { |
|
|
|
|
fileprivate func _baseRequest(servicePath: String, method: HTTPMethod, requiresToken: Bool? = nil) throws -> URLRequest { |
|
|
|
|
let urlString = baseURL + servicePath |
|
|
|
|
guard let url = URL(string: urlString) else { |
|
|
|
|
throw ServiceError.urlCreationError(url: urlString) |
|
|
|
|
@ -160,18 +177,18 @@ public class Services { |
|
|
|
|
// MARK: - Services |
|
|
|
|
|
|
|
|
|
public func get<T: Storable>() async throws -> [T] { |
|
|
|
|
let getRequest = try _getRequest(servicePath: T.resourceName() + "/", requiresToken: T.requestsRequiresToken()) |
|
|
|
|
let getRequest = try _getRequest(type: T.self) |
|
|
|
|
return try await self._runRequest(getRequest) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public func post<T: Storable>(_ instance: T) async throws -> T { |
|
|
|
|
var postRequest = try self._postRequest(servicePath: T.resourceName() + "/", requiresToken: T.requestsRequiresToken()) |
|
|
|
|
var postRequest = try self._postRequest(type: T.self) |
|
|
|
|
postRequest.httpBody = try jsonEncoder.encode(instance) |
|
|
|
|
return try await self._runRequest(postRequest) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public func put<T: Storable>(_ instance: T) async throws -> T { |
|
|
|
|
var postRequest = try self._putRequest(servicePath: T.resourceName() + "/" + instance.id + "/", requiresToken: T.requestsRequiresToken()) |
|
|
|
|
var postRequest = try self._putRequest(type: T.self, id: instance.stringId) |
|
|
|
|
postRequest.httpBody = try jsonEncoder.encode(instance) |
|
|
|
|
return try await self._runRequest(postRequest) |
|
|
|
|
} |
|
|
|
|
@ -190,14 +207,16 @@ public class Services { |
|
|
|
|
request.httpBody = apiCall.body.data(using: .utf8) |
|
|
|
|
request.setValue("application/json", forHTTPHeaderField: "Content-Type") |
|
|
|
|
|
|
|
|
|
do { |
|
|
|
|
let token = try self.keychainStore.getToken() |
|
|
|
|
// Logger.log("current token = \(token)") |
|
|
|
|
request.setValue("Token \(token)", forHTTPHeaderField: "Authorization") |
|
|
|
|
} catch { |
|
|
|
|
Logger.log("missing token") |
|
|
|
|
|
|
|
|
|
if let method = HTTPMethod(rawValue: apiCall.method), self._isTokenRequired(type: T.self, method: method) { |
|
|
|
|
do { |
|
|
|
|
let token = try self.keychainStore.getToken() |
|
|
|
|
request.setValue("Token \(token)", forHTTPHeaderField: "Authorization") |
|
|
|
|
} catch { |
|
|
|
|
Logger.log("missing token") |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return request |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|