diff --git a/Sources/CuteNetwork/Cute.swift b/Sources/CuteNetwork/Cute.swift index ed09fd5..7d8f73a 100644 --- a/Sources/CuteNetwork/Cute.swift +++ b/Sources/CuteNetwork/Cute.swift @@ -11,14 +11,19 @@ class Cute: NSObject, NetworkRouter, URLSessionDelegate /// Properties private var task: URLSessionTask? /// petit(_ root: EndPoint, petitLogVisible: Bool) async throws -> Data 함수를 통해 받은 Data를 파싱해주는 함수입니다. - func petit(_ root: EndPoint, petitLogVisible: Bool = true) async throws -> T{ - let result = try await petit(root, petitLogVisible: petitLogVisible) + func petit(_ root: EndPoint, petitLogVisible: Bool = true) async throws -> T { do { + let result = try await petit(root, petitLogVisible: petitLogVisible) + let decoder = JSONDecoder() let data = try decoder.decode(T.self, from: result) + return data } catch { - throw NetworkError.parsingError + /// [1] `result` error handling + if let networkError = error as? NetworkError { throw networkError } + /// [2] `Decode fail` error handling + else { throw NetworkError.parsingError } } } /// petit(_ route: EndPoint, logAccess: Bool, completion: @escaping NetworkRouterCompletion)를 받아 @@ -27,13 +32,25 @@ class Cute: NSObject, NetworkRouter, URLSessionDelegate return try await withCheckedThrowingContinuation({ value in petit(root, logAccess: petitLogVisible) { data, response, error in if let error { - value.resume(throwing: error) - } else if let data { - value.resume(returning: data) - } else { - value.resume(throwing: NetworkError.noData) + value.resume(throwing: error as? NetworkError ?? NetworkError.custom(message: error.localizedDescription)) } + if let response = response as? HTTPURLResponse { + let result = ResponseHandler.handleNetworkResponse(response) + switch result { + case .success: + guard let data else { + value.resume(throwing: NetworkError.custom(message: "데이터를 받지 못했습니다.")) + return + } + value.resume(returning: data) + case .failure(let message): + guard let _ = data else { + value.resume(throwing: NetworkError.custom(message: message)) + return + } + } + } } }) } @@ -116,11 +133,6 @@ fileprivate extension Cute { func addHeaders(_ headers: HTTPHeaders?, request: inout URLRequest) { guard let headers = headers else { return } - - let _ = headers.map { request.setValue($0, forHTTPHeaderField: $1) } - -// for (key, value) in headers { -// request.setValue(value, forHTTPHeaderField: key) -// } + headers.forEach { request.setValue($0, forHTTPHeaderField: $1) } } } diff --git a/Sources/CuteNetwork/Encodable+parameter.swift b/Sources/CuteNetwork/Encodable+parameter.swift new file mode 100644 index 0000000..119bb72 --- /dev/null +++ b/Sources/CuteNetwork/Encodable+parameter.swift @@ -0,0 +1,17 @@ +// +// Encodable+parameter.swift +// +// +// Created by DEV IOS on 2023/11/30. +// + +import Foundation + +extension Encodable { + var toParameter: [String: Any]? { + guard let object = try? JSONEncoder().encode(self) else { return nil } + guard let dictionary = try? JSONSerialization.jsonObject(with: object, options: []) + as? [String: Any] else { return nil } + return dictionary + } +} diff --git a/Sources/CuteNetwork/FormParameterEncoder.swift b/Sources/CuteNetwork/FormParameterEncoder.swift index aa449f3..d9f96dd 100644 --- a/Sources/CuteNetwork/FormParameterEncoder.swift +++ b/Sources/CuteNetwork/FormParameterEncoder.swift @@ -1,5 +1,5 @@ // -// FORMParameterEncoder.swift +// FormarameterEncoder.swift // // // Created by mino on 2023/11/29. @@ -7,7 +7,7 @@ import Foundation -public struct FORMParameterEncoder: ParameterEncoder { +public struct FormParameterEncoder: ParameterEncoder { public func encode(urlRequest: inout URLRequest, with parameters: Parameters) throws { var parameterArray = [String]() for param in parameters { diff --git a/Sources/CuteNetwork/NetworkLogger.swift b/Sources/CuteNetwork/NetworkLogger.swift index 9576f0b..0ce1da1 100644 --- a/Sources/CuteNetwork/NetworkLogger.swift +++ b/Sources/CuteNetwork/NetworkLogger.swift @@ -11,9 +11,6 @@ class NetworkLogger { static func log(request: URLRequest) { - debugPrint("🥚 [NetworkLogger Start]") - defer { debugPrint("🐥 [NetworkLogger End]") } - let urlAsString = request.url?.absoluteString ?? "" let urlComponents = NSURLComponents(string: urlAsString) @@ -21,27 +18,30 @@ class NetworkLogger { let path = "\(urlComponents?.path ?? "")" let query = "\(urlComponents?.query ?? "")" let host = "\(urlComponents?.host ?? "")" - debugPrint("🐣 [NetworkLogger Request] URL: \(urlAsString)\n") - debugPrint("🐣 [NetworkLogger Request] Method: \(method)") - debugPrint("🐣 [NetworkLogger Request] Path: \(path)") - debugPrint("🐣 [NetworkLogger Request] query: \(query)") - var logOutput = """ - \(urlAsString) \n\n - \(method) \(path)?\(query) HTTP/1.1 \n - HOST: \(host)\n - """ var bodyLog: String = "" - - for (key, value) in request.allHTTPHeaderFields ?? [:] { - logOutput += "\(key): \(value) \n" - } + + let headerLog = (request.allHTTPHeaderFields ?? [:]) + .map { "\($0.key): \($0.value)" } + .joined(separator: "\n") + if let body = request.httpBody { bodyLog += "\n \(NSString(data: body, encoding: String.Encoding.utf8.rawValue) ?? "")" } + debugPrint("🥚 [NetworkLogger Start]") + defer { debugPrint("🐥 [NetworkLogger End]") } + debugPrint("🐣 [NetworkLogger Request] URL: \(urlAsString)\n") + debugPrint("🐣 [NetworkLogger Request] Method: \(method)") + debugPrint("🐣 [NetworkLogger Request] Path: \(path)") + debugPrint("🐣 [NetworkLogger Request] query: \(query)") + #if DEBUG /// debugPrint는 멀티라인을 지원하지 않기 때문에 print로 사용하고 debug처리 + print(""" + "🐣 [NetworkLogger Header] header:\n \(headerLog)"\n + """) + print(""" "🐣 [NetworkLogger Request] body:\n \(bodyLog)"\n """) diff --git a/Sources/CuteNetwork/ParameterEncoding.swift b/Sources/CuteNetwork/ParameterEncoding.swift index db3e4f9..b3cd3a7 100644 --- a/Sources/CuteNetwork/ParameterEncoding.swift +++ b/Sources/CuteNetwork/ParameterEncoding.swift @@ -35,7 +35,7 @@ public enum ParameterEncoding { case .formEncoding: guard let bodyParameters = bodyParameters else { return } - try FORMParameterEncoder().encode(urlRequest: &urlRequest, with: bodyParameters) + try FormParameterEncoder().encode(urlRequest: &urlRequest, with: bodyParameters) } } catch { throw error diff --git a/Tests/CuteNetworkTests/CuteNetworkTests.swift b/Tests/CuteNetworkTests/CuteNetworkTests.swift index 911c604..30e8b8a 100644 --- a/Tests/CuteNetworkTests/CuteNetworkTests.swift +++ b/Tests/CuteNetworkTests/CuteNetworkTests.swift @@ -2,10 +2,42 @@ import XCTest @testable import CuteNetwork final class CuteNetworkTests: XCTestCase { - func testExample() throws { + enum MockEndpoint: EndPointType { + case test + + var baseURL: URL { + return URL(string: "123")! + } + + var path: String { + return "" + } + + var httpMethod: CuteNetwork.HTTPMethod { + return .get + } + + var task: CuteNetwork.HTTPTask { + return .request + } + + var headers: CuteNetwork.HTTPHeaders? { + return [:] + } + } + + + func testExample() async throws { + + let cute = Cute() + do { + let a = try await cute.petit(.test, petitLogVisible: false) +// XCTAssertNotEqual(a, Data()) + } catch { + print("error: \(error)") + } // This is an example of a functional test case. // Use XCTAssert and related functions to verify your tests produce the correct // results. - XCTAssertEqual(CuteNetwork().text, "Hello, World!") } }