-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Split recording to logger, interceptor and listener (#9)
* Split recording to logger, interceptor and listener * bug fix in swizzling and fake protocol * fix grpc observer
- Loading branch information
Showing
6 changed files
with
222 additions
and
34 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
143 changes: 143 additions & 0 deletions
143
Sources/NetShears/URLProtocol/NetwrokListenerUrlProtocol.swift
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
// | ||
// NetwrokListenerUrlProtocol.swift | ||
// NetShears | ||
// | ||
// Created by Mehdi Mirzaie on 6/9/21. | ||
// | ||
|
||
import Foundation | ||
|
||
class NetwrokListenerUrlProtocol: URLProtocol { | ||
|
||
struct Constants { | ||
static let RequestHandledKey = "NetworkListenerUrlProtocol" | ||
} | ||
|
||
var session: URLSession? | ||
var sessionTask: URLSessionDataTask? | ||
var currentRequest: NetShearsRequestModel? | ||
lazy var requestObserver: RequestObserverProtocol = { | ||
RequestObserver(options: [ | ||
RequestBroadcast.shared | ||
]) | ||
}() | ||
|
||
override init(request: URLRequest, cachedResponse: CachedURLResponse?, client: URLProtocolClient?) { | ||
super.init(request: request, cachedResponse: cachedResponse, client: client) | ||
|
||
if session == nil { | ||
session = URLSession(configuration: .default, delegate: self, delegateQueue: nil) | ||
} | ||
} | ||
|
||
override class func canInit(with request: URLRequest) -> Bool { | ||
|
||
if NetwrokListenerUrlProtocol.property(forKey: Constants.RequestHandledKey, in: request) != nil { | ||
return false | ||
} | ||
return true | ||
} | ||
|
||
override class func canonicalRequest(for request: URLRequest) -> URLRequest { | ||
return request | ||
} | ||
|
||
override func startLoading() { | ||
let newRequest = ((request as NSURLRequest).mutableCopy() as? NSMutableURLRequest)! | ||
NetwrokListenerUrlProtocol.setProperty(true, forKey: Constants.RequestHandledKey, in: newRequest) | ||
sessionTask = session?.dataTask(with: newRequest as URLRequest) | ||
sessionTask?.resume() | ||
|
||
currentRequest = NetShearsRequestModel(request: newRequest, session: session) | ||
if let request = currentRequest { | ||
requestObserver.newRequestArrived(request) | ||
} | ||
} | ||
|
||
override func stopLoading() { | ||
sessionTask?.cancel() | ||
currentRequest?.httpBody = body(from: request) | ||
if let startDate = currentRequest?.date{ | ||
currentRequest?.duration = fabs(startDate.timeIntervalSinceNow) * 1000 //Find elapsed time and convert to milliseconds | ||
} | ||
currentRequest?.isFinished = true | ||
|
||
if let request = currentRequest { | ||
requestObserver.newRequestArrived(request) | ||
} | ||
session?.invalidateAndCancel() | ||
} | ||
|
||
private func body(from request: URLRequest) -> Data? { | ||
/// The receiver will have either an HTTP body or an HTTP body stream only one may be set for a request. | ||
/// A HTTP body stream is preserved when copying an NSURLRequest object, | ||
/// but is lost when a request is archived using the NSCoding protocol. | ||
// return request.httpBody ?? request.httpBodyStream?.readfully() | ||
return nil | ||
} | ||
|
||
deinit { | ||
session = nil | ||
sessionTask = nil | ||
currentRequest = nil | ||
} | ||
} | ||
|
||
extension NetwrokListenerUrlProtocol: URLSessionDataDelegate { | ||
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) { | ||
client?.urlProtocol(self, didLoad: data) | ||
if currentRequest?.dataResponse == nil{ | ||
currentRequest?.dataResponse = data | ||
} | ||
else{ | ||
currentRequest?.dataResponse?.append(data) | ||
} | ||
} | ||
|
||
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) { | ||
let policy = URLCache.StoragePolicy(rawValue: request.cachePolicy.rawValue) ?? .notAllowed | ||
client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: policy) | ||
currentRequest?.initResponse(response: response) | ||
completionHandler(.allow) | ||
} | ||
|
||
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { | ||
if let error = error { | ||
currentRequest?.errorClientDescription = error.localizedDescription | ||
client?.urlProtocol(self, didFailWithError: error) | ||
} else { | ||
client?.urlProtocolDidFinishLoading(self) | ||
} | ||
} | ||
|
||
func urlSession(_ session: URLSession, task: URLSessionTask, willPerformHTTPRedirection response: HTTPURLResponse, newRequest request: URLRequest, completionHandler: @escaping (URLRequest?) -> Void) { | ||
client?.urlProtocol(self, wasRedirectedTo: request, redirectResponse: response) | ||
completionHandler(request) | ||
} | ||
|
||
func urlSession(_ session: URLSession, didBecomeInvalidWithError error: Error?) { | ||
guard let error = error else { return } | ||
currentRequest?.errorClientDescription = error.localizedDescription | ||
client?.urlProtocol(self, didFailWithError: error) | ||
} | ||
|
||
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { | ||
let protectionSpace = challenge.protectionSpace | ||
let sender = challenge.sender | ||
|
||
if protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust { | ||
if let serverTrust = protectionSpace.serverTrust { | ||
let credential = URLCredential(trust: serverTrust) | ||
sender?.use(credential, for: challenge) | ||
completionHandler(.useCredential, credential) | ||
return | ||
} | ||
} | ||
} | ||
|
||
func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) { | ||
client?.urlProtocolDidFinishLoading(self) | ||
} | ||
} | ||
|
||
|