@@ -10,7 +10,7 @@ import UIKit
1010
1111class Reporter : NSObject {
1212 var session : URLSession ?
13- var pendingUploadEvent : UploadEvent ?
13+ var pendingEvents : [ ObjectIdentifier : Codable ] = [ : ]
1414
1515 var jsonEncoder : JSONEncoder
1616
@@ -68,7 +68,7 @@ class Reporter: NSObject {
6868 regionCode = locale. regionCode
6969 }
7070
71- self . pendingUploadEvent = UploadEvent (
71+ let event = UploadEvent (
7272 startTime: startTime,
7373 endTime: endTime,
7474 fileSize: fileSize,
@@ -83,34 +83,38 @@ class Reporter: NSObject {
8383 regionCode: regionCode
8484 )
8585
86- let request = self . generateRequest ( url: URL ( string: " https://mobile.muxanalytics.com " ) !)
87-
88- let dataTask = session? . dataTask ( with: request as URLRequest , completionHandler: { ( data, response, error) -> Void in
89- self . pendingUploadEvent = nil
90- } )
91- dataTask? . resume ( )
86+ send (
87+ event: event,
88+ url: url
89+ )
9290 }
9391
94- func serializePendingEvent( ) throws -> Data {
95- return try jsonEncoder. encode ( pendingUploadEvent)
96- }
92+ func send< Event: Codable > (
93+ event: Event ,
94+ url: URL
95+ ) {
96+ guard let httpBody = try ? jsonEncoder. encode ( event) else {
97+ return
98+ }
9799
98- private func generateRequest( url: URL ) -> URLRequest {
99- let request = NSMutableURLRequest ( url: url,
100- cachePolicy: . useProtocolCachePolicy,
101- timeoutInterval: 10.0 )
102- request. httpMethod = " POST "
103- request. setValue ( " application/json " , forHTTPHeaderField: " Accept " )
104- request. setValue ( " application/json " , forHTTPHeaderField: " Content-Type " )
100+ let request = NSMutableURLRequest . make (
101+ url: url,
102+ httpBody: httpBody
103+ )
104+
105+ guard let dataTask = session? . dataTask (
106+ with: request as URLRequest
107+ ) else {
108+ return
109+ }
110+
111+ let taskID = ObjectIdentifier ( dataTask)
105112
106- // FIXME: If this fails, an event without a payload
107- // is sent which probably isn't what we want
108- do {
109- let jsonData = try serializePendingEvent ( )
110- request. httpBody = jsonData
111- } catch _ as NSError { }
113+ pendingEvents [
114+ taskID
115+ ] = event
112116
113- return request as URLRequest
117+ dataTask . resume ( )
114118 }
115119}
116120
@@ -245,12 +249,30 @@ extension Reporter {
245249// TODO: Implement as a separate object so the URLSession
246250// can become non-optional, which removes a bunch of edge cases
247251extension Reporter : URLSessionDelegate , URLSessionTaskDelegate {
248- public func urlSession( _ session: URLSession , task: URLSessionTask , willPerformHTTPRedirection response: HTTPURLResponse , newRequest request: URLRequest , completionHandler: @escaping ( URLRequest ? ) -> Swift . Void ) {
249- if ( self . pendingUploadEvent != nil ) {
250- if let redirectUrl = request. url {
251- let request = self . generateRequest ( url: redirectUrl)
252- completionHandler ( request)
252+ func urlSession( _ session: URLSession , task: URLSessionTask , willPerformHTTPRedirection response: HTTPURLResponse , newRequest request: URLRequest , completionHandler: @escaping ( URLRequest ? ) -> Swift . Void ) {
253+
254+ if let pendingEvent = pendingEvents [ ObjectIdentifier ( task) ] , let redirectURL = request. url {
255+
256+ guard let httpBody = try ? jsonEncoder. encode ( pendingEvent) else {
257+ completionHandler ( nil )
258+ return
253259 }
260+
261+ // TODO: This can be URLRequest instead of NSMutableURLRequest
262+ // test URLRequest-based construction in case
263+ // for any weirdness
264+ let request = NSMutableURLRequest . make (
265+ url: redirectURL,
266+ httpBody: httpBody
267+ )
268+
269+ completionHandler ( request as URLRequest )
254270 }
255271 }
272+
273+ func urlSession( _ session: URLSession , task: URLSessionTask , didCompleteWithError error: Error ? ) {
274+ pendingEvents [
275+ ObjectIdentifier ( task)
276+ ] = nil
277+ }
256278}
0 commit comments