diff --git a/Sources/SimpleNetworking/SimpleNetworking.swift b/Sources/SimpleNetworking/SimpleNetworking.swift index 165fcd7..91e92d1 100644 --- a/Sources/SimpleNetworking/SimpleNetworking.swift +++ b/Sources/SimpleNetworking/SimpleNetworking.swift @@ -14,8 +14,6 @@ import Foundation /// /// This class is ment for simple networking tasks. /// -/// it contains no fancy functions. -/// /// [https://github.com/0xWDG/SimpleNetworking](https://github.com/0xWDG/SimpleNetworking) open class SimpleNetworking { /// Shared instance diff --git a/Sources/SimpleNetworking/SimpleNetworking/WebSocket.swift b/Sources/SimpleNetworking/SimpleNetworking/WebSocket.swift index 1539b0a..0f832f6 100644 --- a/Sources/SimpleNetworking/SimpleNetworking/WebSocket.swift +++ b/Sources/SimpleNetworking/SimpleNetworking/WebSocket.swift @@ -21,7 +21,8 @@ extension SimpleNetworking { WSSocket?.resume() readMessage() } - + + /// Read message from websocket private func readMessage() { WSSocket?.receive { result in do { diff --git a/Sources/SimpleNetworking/SimpleNetworking/createHTTPBody.swift b/Sources/SimpleNetworking/SimpleNetworking/createHTTPBody.swift index 52d48b8..b623184 100644 --- a/Sources/SimpleNetworking/SimpleNetworking/createHTTPBody.swift +++ b/Sources/SimpleNetworking/SimpleNetworking/createHTTPBody.swift @@ -13,6 +13,9 @@ import Foundation extension SimpleNetworking { /// httpBody Method for internal use + /// + /// - Parameter value: Value in `[String: Codable]`, `Codable` or Plain text + /// - Returns: Encoded data func createHTTPBody(with value: Any?) -> Data? { switch self.postType { case .json: diff --git a/Sources/SimpleNetworking/SimpleNetworking/exec.swift b/Sources/SimpleNetworking/SimpleNetworking/exec.swift index c4b3066..80124c6 100644 --- a/Sources/SimpleNetworking/SimpleNetworking/exec.swift +++ b/Sources/SimpleNetworking/SimpleNetworking/exec.swift @@ -11,6 +11,13 @@ import Foundation extension SimpleNetworking { + /// Execute request + /// - Parameters: + /// - request: URL Request + /// - file: Caller's filename + /// - line: Caller's line number + /// - function: Caller's function name + /// - Returns: ``NetworkResponse`` internal func exec( with request: URLRequest, file: String = #file, @@ -81,6 +88,13 @@ extension SimpleNetworking { } } + /// Execute request (legacy, non-async) + /// - Parameters: + /// - request: URL Request + /// - file: Caller's filename + /// - line: Caller's line number + /// - function: Caller's function name + /// - Returns: ``NetworkResponse`` internal func exec( with request: URLRequest, completionHandler: @escaping (NetworkResponse) -> Void, diff --git a/Sources/SimpleNetworking/Structs/Debug.swift b/Sources/SimpleNetworking/Structs/Debug.swift index 5b78c71..8279d26 100644 --- a/Sources/SimpleNetworking/Structs/Debug.swift +++ b/Sources/SimpleNetworking/Structs/Debug.swift @@ -15,16 +15,22 @@ extension SimpleNetworking { public struct Debug { /// Debug: NSURLRequest public var requestURL: Bool = false + /// Debug: sent HTTP Headers public var requestHeaders: Bool = false + /// Debug: sent Cookies public var requestCookies: Bool = false + /// Debug: sent Body public var requestBody: Bool = false + /// Debug: received HTTP Headers public var responseHeaders: Bool = false + /// Debug: received Body public var responseBody: Bool = false + /// Debug: received JSON (if any) public var responseJSON: Bool = false } diff --git a/Sources/SimpleNetworking/Structs/HTTPMethod.swift b/Sources/SimpleNetworking/Structs/HTTPMethod.swift index 5f88a40..9e56e34 100644 --- a/Sources/SimpleNetworking/Structs/HTTPMethod.swift +++ b/Sources/SimpleNetworking/Structs/HTTPMethod.swift @@ -15,16 +15,19 @@ extension SimpleNetworking { public enum HTTPMethod { /// HTTP GET case get + /// HTTP PUT /// /// - parameters: /// - value: A value to put case put(Any?) + /// HTTP POST /// /// - parameters: /// - value: A value to post case post(Any?) + /// HTTP DELETE /// /// - parameters: @@ -32,6 +35,9 @@ extension SimpleNetworking { case delete(Any?) /// Method for internal use + /// + /// Method used for the HTTP Request. + /// This can be `GET`, `PUT`, `POST`, `DELETE`. var method: String { switch self { case .get: diff --git a/Sources/SimpleNetworking/Structs/NetworkResponse.swift b/Sources/SimpleNetworking/Structs/NetworkResponse.swift index abb5814..70afd7a 100644 --- a/Sources/SimpleNetworking/Structs/NetworkResponse.swift +++ b/Sources/SimpleNetworking/Structs/NetworkResponse.swift @@ -36,6 +36,43 @@ extension SimpleNetworking { /// Request public var request: URLRequest + + /// Request as cURL command. + public var cURL: String { + let cURL = "curl" + let method = "-X \(request.httpMethod ?? "GET")" + let url = request.url.flatMap { "--url '\($0.absoluteString)'" } + var cookieString: String? = nil + let header = request.allHTTPHeaderFields? + .map { "-H '\($0): \($1)'" } + .joined(separator: " ") + + + if let cookies = cookies, + let cookieValue = HTTPCookie.requestHeaderFields(with: cookies)["Cookie"] { + cookieString = "-H 'Cookie: \(cookieValue)'" + } + + let data: String? + if let httpBody = request.httpBody, !httpBody.isEmpty { + if let bodyString = String(data: httpBody, encoding: .utf8) { // json and plain text + let escaped = bodyString + .replacingOccurrences(of: "'", with: "'\\''") + data = "--data '\(escaped)'" + } else { // Binary data + let hexString = httpBody + .map { String(format: "%02X", $0) } + .joined() + data = #"--data "$(echo '\#(hexString)' | xxd -p -r)""# + } + } else { + data = nil + } + + return [cURL, method, url, header, cookieString, data] + .compactMap { $0 } + .joined(separator: " ") + } /// Decode to an Codable type /// - Parameter strategy: decoding strategy @@ -56,7 +93,7 @@ extension SimpleNetworking { decoder.keyDecodingStrategy = strategy return try decoder.decode(T.self, from: data) } catch { - print("\(file):\(line) \(function):\r\n Decoding error", error) + print("\(file):\(line) \(function):\r\nDecoding error", error) return nil } } diff --git a/Sources/SimpleNetworking/Structs/NetworkingError.swift b/Sources/SimpleNetworking/Structs/NetworkingError.swift index 51ee501..2efb051 100644 --- a/Sources/SimpleNetworking/Structs/NetworkingError.swift +++ b/Sources/SimpleNetworking/Structs/NetworkingError.swift @@ -13,6 +13,7 @@ import Foundation extension SimpleNetworking { /// Networking error (generator) public struct NetworkingError: Error { + /// Error message let message: String /// Initialize networking error diff --git a/Sources/SimpleNetworking/Structs/POSTType.swift b/Sources/SimpleNetworking/Structs/POSTType.swift index 75b434c..ca59402 100644 --- a/Sources/SimpleNetworking/Structs/POSTType.swift +++ b/Sources/SimpleNetworking/Structs/POSTType.swift @@ -12,6 +12,12 @@ import Foundation extension SimpleNetworking { + /// Post Type + /// + /// The following types are supported: + /// - `json` for JSON based posts. + /// - `plain` for Plain text (eg own encoder). + /// - `graphQL` for graphQL (JSON) public enum POSTType { case json, plain, graphQL } diff --git a/Sources/SimpleNetworking/Structs/SNMock.swift b/Sources/SimpleNetworking/Structs/SNMock.swift index a31f027..bfe4aea 100644 --- a/Sources/SimpleNetworking/Structs/SNMock.swift +++ b/Sources/SimpleNetworking/Structs/SNMock.swift @@ -9,17 +9,36 @@ import Foundation /// Simple Networking Mock public struct SNMock { + /// Mocked HTTP Response data public let data: Data? + + /// Mocked HTTP Response public let response: URLResponse? + + /// Mocked HTTP Response status code public let statusCode: Int? = 200 - public let error: Error? + /// Mocked Error (if any) + public let error: Error? + + /// Initialize a mocked HTTP Response + /// - Parameters: + /// - data: Mocked HTTP Response data + /// - response: Mocked HTTP Response + /// - statusCode: Mocked HTTP Response status code + /// - error: Mocked Error (if any) public init(data: Data?, response: URLResponse?, statusCode: Int? = 200, error: Error?) { self.data = data self.response = response self.error = error } - + + /// Initialize a mocked HTTP Response + /// - Parameters: + /// - data: Mocked HTTP Response data + /// - response: Mocked HTTP Response + /// - statusCode: Mocked HTTP Response status code + /// - error: Mocked Error (if any) public init(data: String?, response: URLResponse?, statusCode: Int? = 200, error: Error?) { self.data = data?.data(using: .utf8) self.response = response