Skip to content

Commit af98170

Browse files
andrewjl-muxcjpillsbury
authored andcommitted
Add uploadURL to UploadEvent (#42)
* Add uploadURL to upload event * Report uploadURL, add test to validate payload * Back out UIDevice and Locale from UploadEvent initializer * Reuse JSONEncoder across uploads * Add todo * More todos
1 parent 346d28b commit af98170

File tree

4 files changed

+98
-33
lines changed

4 files changed

+98
-33
lines changed

Sources/MuxUploadSDK/InternalUtilities/Reporter.swift

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,59 @@
66
//
77

88
import Foundation
9+
import UIKit
910

1011
class Reporter: NSObject {
1112
var session: URLSession?
1213
var pendingUploadEvent: UploadEvent?
1314

15+
var jsonEncoder: JSONEncoder
16+
1417
override init() {
18+
let jsonEncoder = JSONEncoder()
19+
jsonEncoder.keyEncodingStrategy = JSONEncoder.KeyEncodingStrategy.convertToSnakeCase
20+
jsonEncoder.outputFormatting = .sortedKeys
21+
self.jsonEncoder = jsonEncoder
22+
1523
super.init()
1624

1725
let sessionConfig: URLSessionConfiguration = URLSessionConfiguration.default
1826
session = URLSession(configuration: sessionConfig, delegate: self, delegateQueue: nil)
1927
}
2028

21-
func report(startTime: TimeInterval, endTime: TimeInterval, fileSize: UInt64, videoDuration: Double) -> Void {
22-
self.pendingUploadEvent = UploadEvent(startTime: startTime, endTime: endTime, fileSize: fileSize, videoDuration: videoDuration)
29+
func report(
30+
startTime: TimeInterval,
31+
endTime: TimeInterval,
32+
fileSize: UInt64,
33+
videoDuration: Double,
34+
uploadURL: URL
35+
) -> Void {
36+
37+
// TODO: Set these using dependency Injection
38+
let locale = Locale.current
39+
let device = UIDevice.current
40+
41+
let regionCode: String?
42+
if #available(iOS 16, *) {
43+
regionCode = locale.language.region?.identifier
44+
} else {
45+
regionCode = locale.regionCode
46+
}
47+
48+
self.pendingUploadEvent = UploadEvent(
49+
startTime: startTime,
50+
endTime: endTime,
51+
fileSize: fileSize,
52+
videoDuration: videoDuration,
53+
uploadURL: uploadURL,
54+
sdkVersion: Version.versionString,
55+
osName: device.systemName,
56+
osVersion: device.systemVersion,
57+
deviceModel: device.model,
58+
appName: Bundle.main.bundleIdentifier,
59+
appVersion: Bundle.main.appVersion,
60+
regionCode: regionCode
61+
)
2362

2463
let request = self.generateRequest(url: URL(string: "https://mobile.muxanalytics.com")!)
2564

@@ -29,6 +68,10 @@ class Reporter: NSObject {
2968
dataTask?.resume()
3069
}
3170

71+
func serializePendingEvent() throws -> Data {
72+
return try jsonEncoder.encode(pendingUploadEvent)
73+
}
74+
3275
private func generateRequest(url: URL) -> URLRequest {
3376
let request = NSMutableURLRequest(url: url,
3477
cachePolicy: .useProtocolCachePolicy,
@@ -37,17 +80,19 @@ class Reporter: NSObject {
3780
request.setValue("application/json", forHTTPHeaderField: "Accept")
3881
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
3982

83+
// FIXME: If this fails, an event without a payload
84+
// is sent which probably isn't what we want
4085
do {
41-
let encoder = JSONEncoder()
42-
encoder.keyEncodingStrategy = JSONEncoder.KeyEncodingStrategy.convertToSnakeCase
43-
let jsonData = try encoder.encode(self.pendingUploadEvent)
86+
let jsonData = try serializePendingEvent()
4487
request.httpBody = jsonData
4588
} catch _ as NSError {}
4689

4790
return request as URLRequest
4891
}
4992
}
5093

94+
// TODO: Implement as a separate object so the URLSession
95+
// can become non-optional, which removes a bunch of edge cases
5196
extension Reporter: URLSessionDelegate, URLSessionTaskDelegate {
5297
public func urlSession(_ session: URLSession, task: URLSessionTask, willPerformHTTPRedirection response: HTTPURLResponse, newRequest request: URLRequest, completionHandler: @escaping (URLRequest?) -> Swift.Void) {
5398
if(self.pendingUploadEvent != nil) {

Sources/MuxUploadSDK/InternalUtilities/UploadEvent.swift

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@
66
//
77

88
import Foundation
9-
import UIKit
109

1110
struct UploadEvent: Codable {
1211
var type = "upload"
1312
var startTime: TimeInterval
1413
var endTime: TimeInterval
1514
var fileSize: UInt64
1615
var videoDuration: Double
16+
var uploadURL: URL
1717

1818
var sdkVersion: String
1919

@@ -26,32 +26,6 @@ struct UploadEvent: Codable {
2626
var appVersion: String?
2727

2828
var regionCode: String?
29-
30-
init(startTime: TimeInterval, endTime: TimeInterval, fileSize: UInt64, videoDuration: Double) {
31-
let locale = Locale.current
32-
let device = UIDevice.current
33-
34-
self.startTime = startTime
35-
self.endTime = endTime
36-
self.fileSize = fileSize
37-
self.videoDuration = videoDuration
38-
39-
self.sdkVersion = Version.versionString
40-
41-
self.osName = device.systemName
42-
self.osVersion = device.systemVersion
43-
44-
self.deviceModel = device.model
45-
46-
self.appName = Bundle.main.bundleIdentifier
47-
self.appVersion = Bundle.main.appVersion
48-
49-
if #available(iOS 16, *) {
50-
self.regionCode = locale.language.region?.identifier
51-
} else {
52-
self.regionCode = locale.regionCode
53-
}
54-
}
5529
}
5630

5731
extension Bundle {

Sources/MuxUploadSDK/Upload/ChunkedFileUploader.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,8 @@ class ChunkedFileUploader {
113113
startTime: success.startTime,
114114
endTime: success.finishTime,
115115
fileSize: fileSize,
116-
videoDuration: duration.seconds
116+
videoDuration: duration.seconds,
117+
uploadURL: uploadInfo.uploadURL
117118
)
118119
}
119120

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
//
2+
// ReporterTests.swift
3+
//
4+
5+
import Foundation
6+
import XCTest
7+
8+
@testable import MuxUploadSDK
9+
10+
class ReporterTests: XCTestCase {
11+
12+
func testUploadEventSerialization() throws {
13+
let reporter = Reporter()
14+
reporter.pendingUploadEvent = UploadEvent(
15+
startTime: 100,
16+
endTime: 103,
17+
fileSize: 1_500_000,
18+
videoDuration: 3.14,
19+
uploadURL: URL(string: "https://www.example.com")!,
20+
sdkVersion: "0.3.1",
21+
osName: "iPadOS",
22+
osVersion: "16.2",
23+
deviceModel: "iPad",
24+
appName: "foo",
25+
appVersion: "14.3.1",
26+
regionCode: "US"
27+
)
28+
29+
let serializedUploadEvent = try reporter.serializePendingEvent()
30+
31+
let json = try XCTUnwrap(
32+
String(
33+
data: serializedUploadEvent,
34+
encoding: .utf8
35+
)
36+
)
37+
38+
XCTAssertEqual(
39+
json,
40+
"{\"app_name\":\"foo\",\"app_version\":\"14.3.1\",\"device_model\":\"iPad\",\"end_time\":103,\"file_size\":1500000,\"os_name\":\"iPadOS\",\"os_version\":\"16.2\",\"region_code\":\"US\",\"sdk_version\":\"0.3.1\",\"start_time\":100,\"type\":\"upload\",\"upload_url\":\"https:\\/\\/www.example.com\",\"video_duration\":3.1400000000000001}"
41+
)
42+
43+
}
44+
45+
}

0 commit comments

Comments
 (0)