Skip to content

Commit

Permalink
fix: improve user-agent with more detail (#74)
Browse files Browse the repository at this point in the history
* adding user agent

* can import UIKit

* Minor fix

* conditional import statements

* minor fix for deviceInfo.

Need to discuss for the 'default value' in case UIKit is unavailable

* added test case and comments
  • Loading branch information
ami-aman authored Nov 3, 2021
1 parent 845f3af commit 4301034
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 1 deletion.
15 changes: 15 additions & 0 deletions Sources/Tracking/DeviceInfo.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import Foundation
#if canImport(UIKit)
import UIKit

internal enum DeviceInfo {
/// Device's model on which SDK is running eg. iPhone12,3
static let deviceInfo: String = UIDevice.deviceModelCode
/// Operating system and version of OS of the Device
static let osInfo : String = "\(UIDevice().systemName) \(UIDevice().systemVersion)"
/// Name of customer's application using the SDK
static let customerAppName : String = Bundle.main.infoDictionary?["CFBundleName"] as? String ?? ""
/// Version of the customer's application using the SDK
static let customerAppVersion : String = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? ""
}
#endif
31 changes: 31 additions & 0 deletions Sources/Tracking/Extensions/DeviceExtension.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import Foundation
#if canImport(UIKit)
import UIKit


/**
Extend `UIDevice` to get user's device information such as
device's model. If running on Simulator `deviceModelCode`
will return values like`x86_64` but when running on a device, this function
returns exact device model for example, `iPhone12,3`

Use case :
To get model detail, simply use

let deviceModelInfo = UIDevice.deviceModelCode
*/
public extension UIDevice {

static let deviceModelCode : String = {

var systemInfo = utsname()
uname(&systemInfo)
let machineMirror = Mirror(reflecting: systemInfo.machine)
let identifier = machineMirror.children.reduce("") { identifier, element in
guard let value = element.value as? Int8, value != 0 else { return identifier }
return identifier + String(UnicodeScalar(UInt8(value)))
}
return identifier
}()
}
#endif
24 changes: 23 additions & 1 deletion Sources/Tracking/Service/HttpClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -111,12 +111,13 @@ extension CIOHttpClient {
let urlSessionConfig = URLSessionConfiguration.ephemeral
let basicAuthHeaderString = "Basic \(getBasicAuthHeaderString(siteId: siteId, apiKey: apiKey))"


urlSessionConfig.allowsCellularAccess = true
urlSessionConfig.timeoutIntervalForResource = 30
urlSessionConfig.timeoutIntervalForRequest = 60
urlSessionConfig.httpAdditionalHeaders = ["Content-Type": "application/json; charset=utf-8",
"Authorization": basicAuthHeaderString,
"User-Agent": "CustomerIO-SDK-iOS/\(SdkVersion.version)"]
"User-Agent": getUserAgent()]

return URLSession(configuration: urlSessionConfig, delegate: nil, delegateQueue: nil)
}
Expand All @@ -127,4 +128,25 @@ extension CIOHttpClient {

return encodedRawHeader.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
}

/**
* getUserAgent - To get `user-agent` header value. This value depends on SDK version
* and device detail such as OS version, device model, customer's app name etc
*
* In case, UIKit is available then this function returns value in following format :
* `Customer.io iOS Client/1.0.0-alpha.16 (iPhone 11 Pro; iOS 14.5) User App/1.0`
*
* Otherwise will return
* `Customer.io iOS Client/1.0.0-alpha.16`
*/
static func getUserAgent() -> String {
var userAgent = "Customer.io iOS Client/"
userAgent += SdkVersion.version
#if canImport(UIKit)
userAgent += " (\(DeviceInfo.deviceInfo); \(DeviceInfo.osInfo))"
userAgent += " \(DeviceInfo.customerAppName)/"
userAgent += DeviceInfo.customerAppVersion
#endif
return userAgent
}
}
16 changes: 16 additions & 0 deletions Tests/Tracking/Service/HttpClientTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -167,4 +167,20 @@ class HttpClientTest: UnitTest {

XCTAssertEqual(actual, expected)
}

func testGetUserAgent() {
let userAgentValue = CIOHttpClient.getUserAgent()

var expectedUserAgent = "Customer.io iOS Client/\(SdkVersion.version)"

#if canImport(UIKit)
let deviceModel = UIDevice.deviceModelCode
let appName = Bundle.main.infoDictionary?["CFBundleName"] as? String ?? ""
let osInfo = "\(UIDevice().systemName) \(UIDevice().systemVersion)"
let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? ""
expectedUserAgent += " (\(deviceModel); \(osInfo)) \(appName)/\(appVersion)"
#endif

XCTAssertEqual(userAgentValue, expectedUserAgent)
}
}

0 comments on commit 4301034

Please sign in to comment.