Remove URL from Apicall and build it dynamically

multistore
Laurent 1 year ago
parent ff76c1cec1
commit 72f4345c1f
  1. 8
      LeStorage/Codables/ApiCall.swift
  2. 38
      LeStorage/Services.swift
  3. 13
      LeStorage/StoredCollection.swift

@ -21,10 +21,10 @@ class ApiCall<T: Storable>: ModelObject, Storable, SomeCall {
var id: String = Store.randomId()
/// The http URL of the call
var url: String
// var url: String
/// The HTTP method of the call: post...
var method: String
var method: HTTPMethod
/// The id of the underlying data
var dataId: String
@ -38,8 +38,8 @@ class ApiCall<T: Storable>: ModelObject, Storable, SomeCall {
/// The date of the last execution
var lastAttemptDate: Date = Date()
init(url: String, method: String, dataId: String, body: String) {
self.url = url
init(method: HTTPMethod, dataId: String, body: String) {
// self.url = url
self.method = method
self.dataId = dataId
self.body = body

@ -7,7 +7,7 @@
import Foundation
public enum HTTPMethod: String, CaseIterable {
public enum HTTPMethod: String, CaseIterable, Codable {
case get = "GET"
case post = "POST"
case put = "PUT"
@ -19,7 +19,7 @@ public enum ServiceError: Error {
case cantConvertToUUID(id: String)
case missingUserName
case responseError(response: String)
case missingToken
// case missingToken
}
fileprivate enum ServiceConf: String {
@ -59,6 +59,7 @@ public class Services {
public init(url: String) {
self.baseURL = url
self.keychainStore = KeychainStore(serverId: url)
Logger.log("create keystore with id: \(url)")
}
fileprivate(set) var baseURL: String
@ -163,13 +164,8 @@ public class Services {
request.httpMethod = method.rawValue
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
if !(requiresToken == false) {
// Logger.log("current token = \(token)")
do {
let token = try self.keychainStore.getToken()
request.addValue("Token \(token)", forHTTPHeaderField: "Authorization")
} catch {
throw ServiceError.missingToken
}
let token = try self.keychainStore.getToken()
request.addValue("Token \(token)", forHTTPHeaderField: "Authorization")
}
return request
@ -200,15 +196,13 @@ public class Services {
}
fileprivate func _request<T: Storable>(from apiCall: ApiCall<T>) throws -> URLRequest {
guard let url = URL(string: apiCall.url) else {
throw ServiceError.urlCreationError(url: apiCall.url)
}
let url = try self._url(from: apiCall)
var request = URLRequest(url: url)
request.httpMethod = apiCall.method
request.httpMethod = apiCall.method.rawValue
request.httpBody = apiCall.body.data(using: .utf8)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
if let method = HTTPMethod(rawValue: apiCall.method), self._isTokenRequired(type: T.self, method: method) {
if self._isTokenRequired(type: T.self, method: apiCall.method) {
do {
let token = try self.keychainStore.getToken()
request.setValue("Token \(token)", forHTTPHeaderField: "Authorization")
@ -220,6 +214,21 @@ public class Services {
return request
}
fileprivate func _url<T: Storable>(from apiCall: ApiCall<T>) throws -> URL {
var stringURL: String = self.baseURL
switch apiCall.method {
case HTTPMethod.put, HTTPMethod.delete:
stringURL += T.path(id: apiCall.dataId)
default:
stringURL += T.path()
}
if let url = URL(string: stringURL) {
return url
} else {
throw ServiceError.urlCreationError(url: stringURL)
}
}
// MARK: - Authentication
public func createAccount<U: UserPasswordBase, V: UserBase>(user: U) async throws -> V {
@ -286,7 +295,6 @@ public class Services {
try self.keychainStore.deleteToken()
}
fileprivate func errorMessageFromResponse(data: Data) -> String? {
do {
if let jsonObject = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any], let stringsArray = jsonObject.values.first as? [String] {

@ -412,7 +412,7 @@ public class StoredCollection<T: Storable>: RandomAccessCollection, SomeCollecti
switch method {
case .delete:
try self.deleteApiCallById(existingCall.id) // delete the existing call as we don't need it
if existingCall.method == HTTPMethod.post.rawValue {
if existingCall.method == HTTPMethod.post {
return nil // if the post has not been done, we can just stop here
} else {
return try self._createCall(instance, method: method) // otherwise it's a put and we want to send the delete
@ -430,16 +430,7 @@ public class StoredCollection<T: Storable>: RandomAccessCollection, SomeCollecti
fileprivate func _createCall(_ instance: T, method: HTTPMethod) throws -> ApiCall<T> {
let baseURL = try _store.service().baseURL
let jsonString = try instance.jsonString()
let url: String
switch method {
case .get, .post:
url = baseURL + T.path()
case .put, .delete:
url = baseURL + T.path(id: instance.stringId)
}
return ApiCall(url: url, method: method.rawValue, dataId: String(instance.id), body: jsonString)
return ApiCall(method: method, dataId: String(instance.id), body: jsonString)
}
/// Prepares a call for execution by updating its properties and adding it to its collection for storage

Loading…
Cancel
Save