Skip to content

Commit

Permalink
Support .cURL on NetworkResponse struct, so you can easily debug …
Browse files Browse the repository at this point in the history
…with cURL
  • Loading branch information
0xWDG committed May 18, 2024
1 parent 3c44bcf commit 6aee28d
Show file tree
Hide file tree
Showing 10 changed files with 97 additions and 6 deletions.
2 changes: 0 additions & 2 deletions Sources/SimpleNetworking/SimpleNetworking.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion Sources/SimpleNetworking/SimpleNetworking/WebSocket.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ extension SimpleNetworking {
WSSocket?.resume()
readMessage()
}


/// Read message from websocket
private func readMessage() {
WSSocket?.receive { result in
do {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
14 changes: 14 additions & 0 deletions Sources/SimpleNetworking/SimpleNetworking/exec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
6 changes: 6 additions & 0 deletions Sources/SimpleNetworking/Structs/Debug.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
6 changes: 6 additions & 0 deletions Sources/SimpleNetworking/Structs/HTTPMethod.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,29 @@ 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:
/// - value: A value to delete
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:
Expand Down
39 changes: 38 additions & 1 deletion Sources/SimpleNetworking/Structs/NetworkResponse.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
}
}
Expand Down
1 change: 1 addition & 0 deletions Sources/SimpleNetworking/Structs/NetworkingError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import Foundation
extension SimpleNetworking {
/// Networking error (generator)
public struct NetworkingError: Error {
/// Error message
let message: String

/// Initialize networking error
Expand Down
6 changes: 6 additions & 0 deletions Sources/SimpleNetworking/Structs/POSTType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
23 changes: 21 additions & 2 deletions Sources/SimpleNetworking/Structs/SNMock.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 6aee28d

Please sign in to comment.