Skip to content

Commit

Permalink
Add ability to have custom HTTP sessions.
Browse files Browse the repository at this point in the history
  • Loading branch information
bsneed committed May 13, 2024
1 parent ef033e8 commit 0d9ab71
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 20 deletions.
14 changes: 12 additions & 2 deletions Sources/Segment/Configuration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,8 @@ public extension Configuration {

/// Specify a custom UserAgent string. This bypasses the OS dependent check entirely.
@discardableResult
func httpSession(_ httpSession: @escaping @autoclosure () -> HTTPSession) -> Configuration {
values.httpSession = httpSession
func userAgent(_ userAgent: String) -> Configuration {
values.userAgent = userAgent
return self
}

Expand All @@ -273,6 +273,16 @@ public extension Configuration {
values.anonymousIdGenerator = generator
return self
}

/// Use a custom HTTP session; Useful for non-apple platforms where Swift networking isn't as mature
/// or has issues to work around.
/// - Parameter httpSession: A class conforming to the HTTPSession protocol
/// - Returns: The current configuration
@discardableResult
func httpSession(_ httpSession: @escaping @autoclosure () -> any HTTPSession) -> Configuration {
values.httpSession = httpSession
return self
}
}

extension Analytics {
Expand Down
2 changes: 1 addition & 1 deletion Sources/Segment/Plugins/SegmentDestination.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public class SegmentDestination: DestinationPlugin, Subscriber, FlushCompletion
internal struct UploadTaskInfo {
let url: URL?
let data: Data?
let task: URLSessionDataTask
let task: DataTask
// set/used via an extension in iOSLifecycleMonitor.swift
typealias CleanupClosure = () -> Void
var cleanup: CleanupClosure? = nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public class HTTPClient {
/// - batch: The array of the events, considered a batch of events.
/// - completion: The closure executed when done. Passes if the task should be retried or not if failed.
@discardableResult
func startBatchUpload(writeKey: String, batch: URL, completion: @escaping (_ result: Result<Bool, Error>) -> Void) -> URLSessionDataTask? {
func startBatchUpload(writeKey: String, batch: URL, completion: @escaping (_ result: Result<Bool, Error>) -> Void) -> (any DataTask)? {
guard let uploadURL = segmentURL(for: apiHost, path: "/b") else {
self.analytics?.reportInternalError(HTTPClientErrors.failedToOpenBatch)
completion(.failure(HTTPClientErrors.failedToOpenBatch))
Expand All @@ -77,7 +77,7 @@ public class HTTPClient {
/// - batch: The array of the events, considered a batch of events.
/// - completion: The closure executed when done. Passes if the task should be retried or not if failed.
@discardableResult
func startBatchUpload(writeKey: String, data: Data, completion: @escaping (_ result: Result<Bool, Error>) -> Void) -> URLSessionDataTask? {
func startBatchUpload(writeKey: String, data: Data, completion: @escaping (_ result: Result<Bool, Error>) -> Void) -> (any UploadTask)? {
guard let uploadURL = segmentURL(for: apiHost, path: "/b") else {
self.analytics?.reportInternalError(HTTPClientErrors.failedToOpenBatch)
completion(.failure(HTTPClientErrors.failedToOpenBatch))
Expand Down
31 changes: 16 additions & 15 deletions Sources/Segment/Utilities/Networking/HTTPSession.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,30 @@ import FoundationNetworking
#endif

public protocol DataTask {
var state: URLSessionTask.State { get }
func resume()
var state: URLSessionTask.State { get }
func resume()
}

public protocol UploadTask: DataTask {}

// An enumeration of default `HTTPSession` configurations to be used
// This can be extended buy consumer to easily refer back to their configured session.
public enum HTTPSessions {
/// An implementation of `HTTPSession` backed by Apple's `URLSession`.
public static func urlSession() -> any HTTPSession {
let configuration = URLSessionConfiguration.ephemeral
configuration.httpMaximumConnectionsPerHost = 2
let session = URLSession(configuration: configuration, delegate: nil, delegateQueue: nil)
return session
}
/// An implementation of `HTTPSession` backed by Apple's `URLSession`.
public static func urlSession() -> any HTTPSession {
let configuration = URLSessionConfiguration.ephemeral
configuration.httpMaximumConnectionsPerHost = 2
let session = URLSession(configuration: configuration, delegate: nil, delegateQueue: nil)
return session
}
}

public protocol HTTPSession {
associatedtype DataTaskType: DataTask
associatedtype UploadTaskType: UploadTask

func uploadTask(with request: URLRequest, fromFile file: URL, completionHandler: @escaping @Sendable (Data?, URLResponse?, (any Error)?) -> Void) -> UploadTaskType
func dataTask(with request: URLRequest, completionHandler: @escaping @Sendable (Data?, URLResponse?, (any Error)?) -> Void) -> DataTaskType
func finishTasksAndInvalidate()
associatedtype DataTaskType: DataTask
associatedtype UploadTaskType: UploadTask

func uploadTask(with request: URLRequest, fromFile file: URL, completionHandler: @escaping @Sendable (Data?, URLResponse?, (any Error)?) -> Void) -> UploadTaskType
func uploadTask(with request: URLRequest, from bodyData: Data?, completionHandler: @escaping @Sendable (Data?, URLResponse?, (any Error)?) -> Void) -> UploadTaskType
func dataTask(with request: URLRequest, completionHandler: @escaping @Sendable (Data?, URLResponse?, (any Error)?) -> Void) -> DataTaskType
func finishTasksAndInvalidate()
}

0 comments on commit 0d9ab71

Please sign in to comment.