93 lines
2.8 KiB
Swift
93 lines
2.8 KiB
Swift
// Copyright 2015-present 650 Industries. All rights reserved.
|
|
|
|
import ExpoModulesCore
|
|
import React
|
|
|
|
#if DEBUG && EX_DEV_CLIENT_NETWORK_INSPECTOR
|
|
|
|
var isHookInstalled = false
|
|
|
|
@objc(EXDevLauncherNetworkInterceptor)
|
|
public final class DevLauncherNetworkInterceptor: NSObject, ExpoRequestCdpInterceptorDelegate {
|
|
private let metroConnection: RCTReconnectingWebSocket
|
|
|
|
@objc
|
|
public init(bundleUrl: URL) {
|
|
assert(Thread.isMainThread)
|
|
self.metroConnection = RCTReconnectingWebSocket(
|
|
url: Self.createNetworkInspectorUrl(bundleUrl: bundleUrl),
|
|
queue: .main)
|
|
self.metroConnection.start()
|
|
super.init()
|
|
|
|
if !isHookInstalled {
|
|
EXDevLauncherUtils.swizzleClassMethod(
|
|
selector: #selector(getter: URLSessionConfiguration.default),
|
|
withSelector: #selector(URLSessionConfiguration.EXDevLauncher_urlSessionConfiguration),
|
|
forClass: URLSessionConfiguration.self
|
|
)
|
|
isHookInstalled = true
|
|
}
|
|
|
|
ExpoRequestCdpInterceptor.shared.setDelegate(self)
|
|
}
|
|
|
|
deinit {
|
|
assert(Thread.isMainThread)
|
|
ExpoRequestCdpInterceptor.shared.setDelegate(nil)
|
|
self.metroConnection.stop()
|
|
}
|
|
|
|
private static func createNetworkInspectorUrl(bundleUrl: URL) -> URL {
|
|
let host = bundleUrl.host ?? "localhost"
|
|
let port = bundleUrl.port ?? 8081
|
|
let scheme = bundleUrl.scheme == "https" ? "wss" : "ws"
|
|
let urlString = "\(scheme)://\(host):\(port)/inspector/network"
|
|
guard let url = URL(string: urlString) else {
|
|
fatalError("Invalid network inspector URL: \(urlString)")
|
|
}
|
|
return url
|
|
}
|
|
|
|
// MARK: ExpoRequestCdpInterceptorDelegate implementations
|
|
|
|
public func dispatch(_ event: String) {
|
|
self.metroConnection.send(Data(event.utf8))
|
|
}
|
|
}
|
|
|
|
extension URLSessionConfiguration {
|
|
private typealias GetterFunc = @convention(c) (AnyObject, Selector) -> URLSessionConfiguration
|
|
|
|
/**
|
|
Swizzled `URLSessionConfiguration.default` for us to add the `EXDevLauncherRequestLoggerProtocol` interceptor
|
|
*/
|
|
@objc
|
|
static func EXDevLauncher_urlSessionConfiguration() -> URLSessionConfiguration {
|
|
guard let config = try? EXDevLauncherUtils.invokeOriginalClassMethod(
|
|
selector: #selector(getter: URLSessionConfiguration.default),
|
|
forClass: URLSessionConfiguration.self
|
|
) as? URLSessionConfiguration else {
|
|
fatalError("Unable to get original URLSessionConfiguration.default")
|
|
}
|
|
var protocolClasses: [AnyClass] = config.protocolClasses ?? []
|
|
if !protocolClasses.contains(where: { $0 == ExpoRequestInterceptorProtocol.self }) {
|
|
protocolClasses.insert(ExpoRequestInterceptorProtocol.self, at: 0)
|
|
}
|
|
config.protocolClasses = protocolClasses
|
|
return config
|
|
}
|
|
}
|
|
|
|
#else
|
|
|
|
@objc(EXDevLauncherNetworkInterceptor)
|
|
public final class DevLauncherNetworkInterceptor: NSObject {
|
|
@objc
|
|
public init(bundleUrl: URL) {
|
|
super.init()
|
|
}
|
|
}
|
|
|
|
#endif
|