141 lines
4.2 KiB
Swift
141 lines
4.2 KiB
Swift
import Foundation
|
|
import GRDB
|
|
|
|
public struct CapturedTraffic: Codable, FetchableRecord, MutablePersistableRecord, Identifiable, Sendable {
|
|
public var id: Int64?
|
|
public var requestId: String
|
|
public var domain: String
|
|
public var url: String
|
|
public var method: String
|
|
public var scheme: String
|
|
public var statusCode: Int?
|
|
public var statusText: String?
|
|
|
|
// Request
|
|
public var requestHeaders: String?
|
|
public var requestBody: Data?
|
|
public var requestBodySize: Int
|
|
public var requestContentType: String?
|
|
public var queryParameters: String?
|
|
|
|
// Response
|
|
public var responseHeaders: String?
|
|
public var responseBody: Data?
|
|
public var responseBodySize: Int
|
|
public var responseContentType: String?
|
|
|
|
// Timing
|
|
public var startedAt: Double
|
|
public var completedAt: Double?
|
|
public var durationMs: Int?
|
|
|
|
// Metadata
|
|
public var isSslDecrypted: Bool
|
|
public var isPinned: Bool
|
|
public var isWebsocket: Bool
|
|
public var isHidden: Bool
|
|
|
|
public var createdAt: Double
|
|
|
|
public static let databaseTableName = "captured_traffic"
|
|
|
|
public mutating func didInsert(_ inserted: InsertionSuccess) {
|
|
id = inserted.rowID
|
|
}
|
|
|
|
public init(
|
|
id: Int64? = nil,
|
|
requestId: String = UUID().uuidString,
|
|
domain: String,
|
|
url: String,
|
|
method: String,
|
|
scheme: String,
|
|
statusCode: Int? = nil,
|
|
statusText: String? = nil,
|
|
requestHeaders: String? = nil,
|
|
requestBody: Data? = nil,
|
|
requestBodySize: Int = 0,
|
|
requestContentType: String? = nil,
|
|
queryParameters: String? = nil,
|
|
responseHeaders: String? = nil,
|
|
responseBody: Data? = nil,
|
|
responseBodySize: Int = 0,
|
|
responseContentType: String? = nil,
|
|
startedAt: Double = Date().timeIntervalSince1970,
|
|
completedAt: Double? = nil,
|
|
durationMs: Int? = nil,
|
|
isSslDecrypted: Bool = false,
|
|
isPinned: Bool = false,
|
|
isWebsocket: Bool = false,
|
|
isHidden: Bool = false,
|
|
createdAt: Double = Date().timeIntervalSince1970
|
|
) {
|
|
self.id = id
|
|
self.requestId = requestId
|
|
self.domain = domain
|
|
self.url = url
|
|
self.method = method
|
|
self.scheme = scheme
|
|
self.statusCode = statusCode
|
|
self.statusText = statusText
|
|
self.requestHeaders = requestHeaders
|
|
self.requestBody = requestBody
|
|
self.requestBodySize = requestBodySize
|
|
self.requestContentType = requestContentType
|
|
self.queryParameters = queryParameters
|
|
self.responseHeaders = responseHeaders
|
|
self.responseBody = responseBody
|
|
self.responseBodySize = responseBodySize
|
|
self.responseContentType = responseContentType
|
|
self.startedAt = startedAt
|
|
self.completedAt = completedAt
|
|
self.durationMs = durationMs
|
|
self.isSslDecrypted = isSslDecrypted
|
|
self.isPinned = isPinned
|
|
self.isWebsocket = isWebsocket
|
|
self.isHidden = isHidden
|
|
self.createdAt = createdAt
|
|
}
|
|
}
|
|
|
|
// MARK: - Computed Properties
|
|
|
|
extension CapturedTraffic {
|
|
public var decodedRequestHeaders: [String: String] {
|
|
guard let data = requestHeaders?.data(using: .utf8),
|
|
let dict = try? JSONDecoder().decode([String: String].self, from: data) else {
|
|
return [:]
|
|
}
|
|
return dict
|
|
}
|
|
|
|
public var decodedResponseHeaders: [String: String] {
|
|
guard let data = responseHeaders?.data(using: .utf8),
|
|
let dict = try? JSONDecoder().decode([String: String].self, from: data) else {
|
|
return [:]
|
|
}
|
|
return dict
|
|
}
|
|
|
|
public var decodedQueryParameters: [String: String] {
|
|
guard let data = queryParameters?.data(using: .utf8),
|
|
let dict = try? JSONDecoder().decode([String: String].self, from: data) else {
|
|
return [:]
|
|
}
|
|
return dict
|
|
}
|
|
|
|
public var startDate: Date {
|
|
Date(timeIntervalSince1970: startedAt)
|
|
}
|
|
|
|
public var formattedDuration: String {
|
|
guard let ms = durationMs else { return "-" }
|
|
if ms < 1000 {
|
|
return "\(ms) ms"
|
|
} else {
|
|
return String(format: "%.1f s", Double(ms) / 1000.0)
|
|
}
|
|
}
|
|
}
|