Last active
May 11, 2024 20:19
-
-
Save JasonCanCode/2aae7f201139c5f4c17327205e0a0317 to your computer and use it in GitHub Desktop.
Print out helpful information on network requests when debugging
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
#if DEBUG | |
/// Use this to print out helpful information on network requests when debugging. | |
/// The functions return strings so I can decide whether to use print statemens or custom breakpoints to log them. | |
public enum NetworkLogger { | |
static func cURLLog(request: URLRequest) -> String { | |
"\n🌎 \(request.cURL)\n" | |
} | |
/// Print an outgoing request to the console with a print statement or custom breakpoint | |
static func requestLog(_ request: URLRequest, includeHeaders: Bool = true, includeBody: Bool = true) -> String { | |
var log: String = "\n🌎 \(request.methodAndPath)" | |
if includeHeaders { | |
log += request.headers | |
} | |
if includeBody { | |
log += request.bodyString | |
} | |
return log | |
} | |
/// Print a successful request to the console with a print statement or custom breakpoint | |
/// - Parameters: | |
/// - data: The JSON response in Data form. If you don't want to log the body of the response, omit this parameter. | |
/// - response: The successful network response | |
/// - Returns: Human readable text for logging in our console. | |
static func requestSuccessLog(data: Foundation.Data? = nil, response: URLResponse) -> String { | |
var log: String = "\n✅ " + response.statusAndPath | |
if let jsonText = data?.asJSONText { | |
log += "\n\(jsonText)" | |
} | |
return log + "\n" | |
} | |
/// Print a failed request to the console with a print statement or custom breakpoint | |
static func requestFailureLog(error: Error, response: URLResponse?) -> String { | |
return "\n🟥 " | |
+ (response?.statusAndPath ?? "") | |
+ "\n " | |
+ error.localizedDescription | |
+ "\n" | |
} | |
} | |
// MARK: - Helper Extensions | |
private extension URLRequest { | |
/// You can use this to print out the cURL of a network request to the console. | |
var cURL: String { | |
"cURL " + methodAndPath + headers + bodyString | |
} | |
var methodAndPath: String { | |
let method = "-X \"\(self.httpMethod ?? "GET")\" " | |
let url: String = "\"\(self.url?.absoluteString ?? "")\" \n" | |
return method + url | |
} | |
var headers: String { | |
var headers = "" | |
if let httpHeaders = self.allHTTPHeaderFields, !httpHeaders.keys.isEmpty { | |
for (key, value) in httpHeaders { | |
headers += "-H '\(key): \(value)'\\ \n" | |
} | |
} | |
return headers | |
} | |
var bodyString: String { | |
guard let text = self.httpBody?.asJSONText else { | |
return "" | |
} | |
return "-d $'\(text)'" | |
} | |
} | |
private extension URLResponse { | |
var statusAndPath: String { | |
var text = "" | |
if let statusCode = (self as? HTTPURLResponse)?.statusCode { | |
text += " (\(statusCode))" | |
} | |
if let path = self.url?.absoluteString { | |
text += " \(path)" | |
} | |
return text | |
} | |
} | |
private extension Foundation.Data { | |
/// You can use this to print out the raw data response of a network request in the console. | |
/// | |
/// In order to get a string that prints nicely in the console, we take a `Data` object, convert it to a JSON dictionary, | |
/// and then convert it back to `Data` to generate our String. | |
var asJSONText: String? { | |
if let jsonString = self.asJSON?.jsonString { | |
return jsonString.isEmpty ? nil : jsonString | |
} else if let jsonArray = self.asJSONArray { | |
let arrayString = jsonArray.reduce("") { result, json -> String in | |
let addition = json.jsonString | |
if result.isEmpty { | |
return addition | |
} else { | |
return result + ",\n" + addition | |
} | |
} | |
return arrayString.isEmpty ? nil : "{\n\(arrayString)\n}" | |
} else { | |
return nil | |
} | |
} | |
var asJSON: [String: Any]? { | |
jsonSerialized as? [String: Any] | |
} | |
var asJSONArray: [[String: Any]]? { | |
jsonSerialized as? [[String: Any]] | |
} | |
var jsonSerialized: Any? { | |
try? JSONSerialization.jsonObject(with: self, options: .allowFragments) | |
} | |
} | |
private extension Dictionary where Key == String, Value == Any { | |
var jsonString: String { | |
do { | |
let data = try JSONSerialization.data(withJSONObject: self, options: .prettyPrinted) | |
return String(data: data, encoding: .utf8) ?? "" | |
} catch _ { | |
return "" | |
} | |
} | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment