120 lines
4.1 KiB
Swift
120 lines
4.1 KiB
Swift
// Copyright 2015-present 650 Industries. All rights reserved.
|
|
|
|
@preconcurrency import ExpoModulesCore
|
|
|
|
private let fetchRequestQueue = DispatchQueue(label: "expo.modules.fetch.RequestQueue")
|
|
@MainActor internal var urlSessionConfigurationProvider: NSURLSessionConfigurationProvider?
|
|
|
|
@MainActor public final class ExpoFetchModule: @preconcurrency Module {
|
|
private lazy var urlSession = createURLSession()
|
|
private let urlSessionDelegate: URLSessionSessionDelegateProxy
|
|
|
|
public required init(appContext: AppContext) {
|
|
urlSessionDelegate = URLSessionSessionDelegateProxy(dispatchQueue: fetchRequestQueue)
|
|
super.init(appContext: appContext)
|
|
}
|
|
|
|
public func definition() -> ModuleDefinition {
|
|
Name("ExpoFetchModule")
|
|
|
|
OnDestroy {
|
|
urlSession.invalidateAndCancel()
|
|
}
|
|
|
|
// swiftlint:disable:next closure_body_length
|
|
Class(NativeResponse.self) {
|
|
Constructor {
|
|
return NativeResponse(dispatchQueue: fetchRequestQueue)
|
|
}
|
|
|
|
AsyncFunction("startStreaming") { (response: NativeResponse) -> Data? in
|
|
return response.startStreaming()
|
|
}.runOnQueue(fetchRequestQueue)
|
|
|
|
AsyncFunction("cancelStreaming") { (response: NativeResponse, _ reason: String) in
|
|
response.cancelStreaming()
|
|
}.runOnQueue(fetchRequestQueue)
|
|
|
|
Property("bodyUsed", \.bodyUsed)
|
|
|
|
Property("_rawHeaders") { (response: NativeResponse) in
|
|
return response.responseInit?.headers ?? []
|
|
}
|
|
|
|
Property("status") { (response: NativeResponse) in
|
|
return response.responseInit?.status ?? -1
|
|
}
|
|
|
|
Property("statusText") { (response: NativeResponse) in
|
|
return response.responseInit?.statusText ?? ""
|
|
}
|
|
|
|
Property("url") { (response: NativeResponse) in
|
|
return response.responseInit?.url ?? ""
|
|
}
|
|
|
|
Property("redirected", \.redirected)
|
|
|
|
AsyncFunction("arrayBuffer") { (response: NativeResponse, promise: Promise) in
|
|
response.waitFor(states: [.bodyCompleted]) { _ in
|
|
let data = response.sink.finalize()
|
|
promise.resolve(data)
|
|
}
|
|
}.runOnQueue(fetchRequestQueue)
|
|
|
|
AsyncFunction("text") { (response: NativeResponse, promise: Promise) in
|
|
response.waitFor(states: [.bodyCompleted]) { _ in
|
|
let data = response.sink.finalize()
|
|
let text = String(decoding: data, as: UTF8.self)
|
|
promise.resolve(text)
|
|
}
|
|
}.runOnQueue(fetchRequestQueue)
|
|
}
|
|
|
|
Class(NativeRequest.self) {
|
|
Constructor { (nativeResponse: NativeResponse) in
|
|
return NativeRequest(response: nativeResponse)
|
|
}
|
|
|
|
AsyncFunction("start") { (request: NativeRequest, url: URL, requestInit: NativeRequestInit, requestBody: Data?, promise: Promise) in
|
|
request.start(
|
|
urlSession: urlSession,
|
|
urlSessionDelegate: urlSessionDelegate,
|
|
url: url,
|
|
requestInit: requestInit,
|
|
requestBody: requestBody
|
|
)
|
|
request.response.waitFor(states: [.responseReceived, .errorReceived]) { state in
|
|
if state == .responseReceived {
|
|
promise.resolve()
|
|
} else if state == .errorReceived {
|
|
promise.reject(request.response.error ?? FetchUnknownException())
|
|
}
|
|
}
|
|
}.runOnQueue(fetchRequestQueue)
|
|
|
|
AsyncFunction("cancel") { (request: NativeRequest) in
|
|
request.cancel(urlSessionDelegate: self.urlSessionDelegate)
|
|
}.runOnQueue(fetchRequestQueue)
|
|
}
|
|
}
|
|
|
|
private func createURLSession() -> URLSession {
|
|
let config: URLSessionConfiguration
|
|
if let urlSessionConfigurationProvider, let concreteConfig = urlSessionConfigurationProvider() {
|
|
config = concreteConfig
|
|
} else {
|
|
config = URLSessionConfiguration.default
|
|
config.httpShouldSetCookies = true
|
|
config.httpCookieAcceptPolicy = .always
|
|
config.httpCookieStorage = HTTPCookieStorage.shared
|
|
|
|
let useWifiOnly = Bundle.main.infoDictionary?["ReactNetworkForceWifiOnly"] as? Bool ?? false
|
|
if useWifiOnly {
|
|
config.allowsCellularAccess = !useWifiOnly
|
|
}
|
|
}
|
|
return URLSession(configuration: config, delegate: urlSessionDelegate, delegateQueue: nil)
|
|
}
|
|
}
|