AcaMate_iOS/AcaMate/5. Manager/APIManager.swift

134 lines
5.2 KiB
Swift

//
// APIController.swift
// AcaMate
//
// Created by Sean Kim on 11/26/24.
//
import Foundation
import Combine
import Alamofire
public class APIManager {
private var cancellables = Set<AnyCancellable>()
// public static let shared = APIManager()
@UserDefault(key: "refresh", defaultValue: "refreshToken") var refresh
@UserDefault(key: "token", defaultValue: "accToken") var accToken
// private init(cancellables: Set<AnyCancellable> = Set<AnyCancellable>()) {
// self.cancellables = cancellables
// }
public func loadAPIData<T: APIResponseProtocol>(_ request: APIRequest<T>) -> Future<T, Error> {
let encoding: ParameterEncoding = (request.method == .get) ? URLEncoding.default : JSONEncoding.default
return Future { promise in
printLog(request.parameters)
AF.request("\(request.url)\(request.path)",
method: request.method,
parameters: request.parameters,
encoding: encoding,
headers: request.headers
)
.validate(statusCode: 200 ..< 300)
.responseDecodable(of: request.decoding) { response in
switch response.result {
case .success(let value):
printLog("Good: \(value)")
promise(.success(value))
case .failure(let error):
printLog("Bad: \(error))")
promise(.failure(error))
}
}
}
}
public func reloadAccessToken() -> Future<Any, Error> {
return Future { [weak self] promise in
guard let self = self else {return}
let request = APIRequest.init(path: "/api/v1/in/app/retryAccess",
parameters: ["refresh": refresh],
decoding: APIResponse<Access>.self)
APIManager().loadAPIData(request)
.sink { completion in
switch completion {
case .failure(let error):
promise(.failure(error))
printLog("\(error)")
case .finished:
printLog("엑세스 토큰 재발급 완료")
break
}
} receiveValue: { response in
guard let accToken = response as? APIResponse<Access> else {
promise(.failure(ACA_ERROR("Unknown ERROR")))
return
}
switch accToken.status.code {
case .success(let code):
if code == "000" {
if let tknData = accToken.data { promise(.success(tknData)) }
}
case .inputErr(let code):
//
promise(.failure(ACA_ERROR("Refresh token ERROR(\(code), \(accToken.status.message)")))
default:
//
promise(.failure(ACA_ERROR("Unknown ERROR")))
}
}
.store(in: &self.cancellables)
}
}
public func loadUserAPIData<T: APIResponseProtocol & Codable>(request: APIRequest<T>) -> Future<T, Error>{
return Future { [weak self] promise in
guard let self = self else {return}
printLog(request.parameters["token"])
loadAPIData(request)
.flatMap { (response: T) -> AnyPublisher<T, Error> in
switch response.status.code {
case .inputErr(let code) where code == "101":
return self.reloadAccessToken()
.flatMap { response -> AnyPublisher<T, Error> in
self.accToken = (response as! Access).access
var updateRequest = request
updateRequest.parameters["token"] = self.accToken
return APIManager().loadAPIData(updateRequest)
.eraseToAnyPublisher()
}
.eraseToAnyPublisher()
default:
return Just(response)
.setFailureType(to: Error.self)
.eraseToAnyPublisher()
}
}
.sink { completion in
switch completion {
case .failure(let error):
promise(.failure(error))
case .finished:
break
}
} receiveValue: { finalResponse in
promise(.success(finalResponse))
}
.store(in: &self.cancellables)
}
}
}