From cc9cd49dfe46fb71326d50f11db5df32111bf282 Mon Sep 17 00:00:00 2001 From: Elliot <35050275+Apache-HB@users.noreply.github.com> Date: Fri, 6 Nov 2020 12:00:09 -0800 Subject: [PATCH] [ch91505] Dynamic header configuration (#128) Allow dynamic configuration of http headers through LDConfig.headerDelegate --- Cartfile | 2 +- LaunchDarkly.podspec | 2 +- LaunchDarkly.xcodeproj/project.pbxproj | 6 ++--- .../xcshareddata/swiftpm/Package.resolved | 4 +-- .../LaunchDarkly/Models/DiagnosticEvent.swift | 2 ++ .../LaunchDarkly/Models/LDConfig.swift | 19 +++++++++++++ .../Networking/DarklyService.swift | 27 ++++++++++++++----- .../LaunchDarkly/Networking/HTTPHeaders.swift | 2 +- .../Cache/CacheConverter.swift | 0 .../Cache/ConnectionInformationStore.swift | 0 .../Cache/DeprecatedCache.swift | 0 .../Cache/DeprecatedCacheModelV2.swift | 0 .../Cache/DeprecatedCacheModelV3.swift | 0 .../Cache/DeprecatedCacheModelV4.swift | 0 .../Cache/DeprecatedCacheModelV5.swift | 0 .../Cache/DiagnosticCache.swift | 0 .../Cache/KeyedValueCache.swift | 0 .../Cache/UserEnvironmentFlagCache.swift | 0 .../ClientServiceFactory.swift | 20 +++++++++++--- .../CwlSysctl.swift | 0 .../DiagnosticReporter.swift | 0 .../EnvironmentReporter.swift | 0 .../ErrorNotifier.swift | 0 .../EventReporter.swift | 0 .../FlagChangeNotifier.swift | 0 .../FlagStore.swift | 0 .../FlagSynchronizer.swift | 6 ++++- .../LDTimer.swift | 0 .../Log.swift | 0 .../NetworkReporter.swift | 0 .../Throttler.swift | 0 .../Mocks/ClientServiceMockFactory.swift | 16 +++++++---- .../Models/DiagnosticEventSpec.swift | 4 ++- .../Cache/CacheConverterSpec.swift | 0 .../Cache/DeprecatedCacheModelV2Spec.swift | 0 .../Cache/DeprecatedCacheModelV3Spec.swift | 0 .../Cache/DeprecatedCacheModelV4Spec.swift | 0 .../Cache/DeprecatedCacheModelV5Spec.swift | 0 .../Cache/DiagnosticCacheSpec.swift | 0 .../Cache/KeyedValueCacheSpec.swift | 0 .../Cache/UserEnvironmentFlagCacheSpec.swift | 0 .../EnvironmentReporterSpec.swift | 0 .../ErrorNotifierSpec.swift | 0 .../EventReporterSpec.swift | 0 .../FlagChangeNotifierSpec.swift | 0 .../FlagStoreSpec.swift | 0 .../FlagSynchronizerSpec.swift | 0 .../LDTimerSpec.swift | 0 .../SynchronizingErrorSpec.swift | 0 .../ThrottlerSpec.swift | 0 Package.resolved | 4 +-- Package.swift | 4 +-- 52 files changed, 88 insertions(+), 30 deletions(-) rename {LaunchDarkly.xcworkspace => LaunchDarkly.xcodeproj/project.xcworkspace}/xcshareddata/swiftpm/Package.resolved (94%) rename LaunchDarkly/LaunchDarkly/{Service Objects => ServiceObjects}/Cache/CacheConverter.swift (100%) rename LaunchDarkly/LaunchDarkly/{Service Objects => ServiceObjects}/Cache/ConnectionInformationStore.swift (100%) rename LaunchDarkly/LaunchDarkly/{Service Objects => ServiceObjects}/Cache/DeprecatedCache.swift (100%) rename LaunchDarkly/LaunchDarkly/{Service Objects => ServiceObjects}/Cache/DeprecatedCacheModelV2.swift (100%) rename LaunchDarkly/LaunchDarkly/{Service Objects => ServiceObjects}/Cache/DeprecatedCacheModelV3.swift (100%) rename LaunchDarkly/LaunchDarkly/{Service Objects => ServiceObjects}/Cache/DeprecatedCacheModelV4.swift (100%) rename LaunchDarkly/LaunchDarkly/{Service Objects => ServiceObjects}/Cache/DeprecatedCacheModelV5.swift (100%) rename LaunchDarkly/LaunchDarkly/{Service Objects => ServiceObjects}/Cache/DiagnosticCache.swift (100%) rename LaunchDarkly/LaunchDarkly/{Service Objects => ServiceObjects}/Cache/KeyedValueCache.swift (100%) rename LaunchDarkly/LaunchDarkly/{Service Objects => ServiceObjects}/Cache/UserEnvironmentFlagCache.swift (100%) rename LaunchDarkly/LaunchDarkly/{Service Objects => ServiceObjects}/ClientServiceFactory.swift (84%) rename LaunchDarkly/LaunchDarkly/{Service Objects => ServiceObjects}/CwlSysctl.swift (100%) rename LaunchDarkly/LaunchDarkly/{Service Objects => ServiceObjects}/DiagnosticReporter.swift (100%) rename LaunchDarkly/LaunchDarkly/{Service Objects => ServiceObjects}/EnvironmentReporter.swift (100%) rename LaunchDarkly/LaunchDarkly/{Service Objects => ServiceObjects}/ErrorNotifier.swift (100%) rename LaunchDarkly/LaunchDarkly/{Service Objects => ServiceObjects}/EventReporter.swift (100%) rename LaunchDarkly/LaunchDarkly/{Service Objects => ServiceObjects}/FlagChangeNotifier.swift (100%) rename LaunchDarkly/LaunchDarkly/{Service Objects => ServiceObjects}/FlagStore.swift (100%) rename LaunchDarkly/LaunchDarkly/{Service Objects => ServiceObjects}/FlagSynchronizer.swift (98%) rename LaunchDarkly/LaunchDarkly/{Service Objects => ServiceObjects}/LDTimer.swift (100%) rename LaunchDarkly/LaunchDarkly/{Service Objects => ServiceObjects}/Log.swift (100%) rename LaunchDarkly/LaunchDarkly/{Service Objects => ServiceObjects}/NetworkReporter.swift (100%) rename LaunchDarkly/LaunchDarkly/{Service Objects => ServiceObjects}/Throttler.swift (100%) rename LaunchDarkly/LaunchDarklyTests/{Service Objects => ServiceObjects}/Cache/CacheConverterSpec.swift (100%) rename LaunchDarkly/LaunchDarklyTests/{Service Objects => ServiceObjects}/Cache/DeprecatedCacheModelV2Spec.swift (100%) rename LaunchDarkly/LaunchDarklyTests/{Service Objects => ServiceObjects}/Cache/DeprecatedCacheModelV3Spec.swift (100%) rename LaunchDarkly/LaunchDarklyTests/{Service Objects => ServiceObjects}/Cache/DeprecatedCacheModelV4Spec.swift (100%) rename LaunchDarkly/LaunchDarklyTests/{Service Objects => ServiceObjects}/Cache/DeprecatedCacheModelV5Spec.swift (100%) rename LaunchDarkly/LaunchDarklyTests/{Service Objects => ServiceObjects}/Cache/DiagnosticCacheSpec.swift (100%) rename LaunchDarkly/LaunchDarklyTests/{Service Objects => ServiceObjects}/Cache/KeyedValueCacheSpec.swift (100%) rename LaunchDarkly/LaunchDarklyTests/{Service Objects => ServiceObjects}/Cache/UserEnvironmentFlagCacheSpec.swift (100%) rename LaunchDarkly/LaunchDarklyTests/{Service Objects => ServiceObjects}/EnvironmentReporterSpec.swift (100%) rename LaunchDarkly/LaunchDarklyTests/{Service Objects => ServiceObjects}/ErrorNotifierSpec.swift (100%) rename LaunchDarkly/LaunchDarklyTests/{Service Objects => ServiceObjects}/EventReporterSpec.swift (100%) rename LaunchDarkly/LaunchDarklyTests/{Service Objects => ServiceObjects}/FlagChangeNotifierSpec.swift (100%) rename LaunchDarkly/LaunchDarklyTests/{Service Objects => ServiceObjects}/FlagStoreSpec.swift (100%) rename LaunchDarkly/LaunchDarklyTests/{Service Objects => ServiceObjects}/FlagSynchronizerSpec.swift (100%) rename LaunchDarkly/LaunchDarklyTests/{Service Objects => ServiceObjects}/LDTimerSpec.swift (100%) rename LaunchDarkly/LaunchDarklyTests/{Service Objects => ServiceObjects}/SynchronizingErrorSpec.swift (100%) rename LaunchDarkly/LaunchDarklyTests/{Service Objects => ServiceObjects}/ThrottlerSpec.swift (100%) diff --git a/Cartfile b/Cartfile index 0a3e85b1..4f6613ef 100644 --- a/Cartfile +++ b/Cartfile @@ -1 +1 @@ -github "launchdarkly/swift-eventsource" ~> 1.1.0 \ No newline at end of file +github "launchdarkly/swift-eventsource" ~> 1.2.0 \ No newline at end of file diff --git a/LaunchDarkly.podspec b/LaunchDarkly.podspec index 7842d35c..ec856ca5 100644 --- a/LaunchDarkly.podspec +++ b/LaunchDarkly.podspec @@ -35,6 +35,6 @@ Pod::Spec.new do |ld| ld.swift_version = '5.0' ld.subspec 'Core' do |es| - es.dependency 'LDSwiftEventSource', '1.1.0' + es.dependency 'LDSwiftEventSource', '1.2.0' end end diff --git a/LaunchDarkly.xcodeproj/project.pbxproj b/LaunchDarkly.xcodeproj/project.pbxproj index 73bfea2c..9af0d40e 100644 --- a/LaunchDarkly.xcodeproj/project.pbxproj +++ b/LaunchDarkly.xcodeproj/project.pbxproj @@ -571,7 +571,7 @@ 833631CA221B5DFA00BA53EE /* ErrorNotifierSpec.swift */, 8354AC75224316C700CDE602 /* Cache */, ); - path = "Service Objects"; + path = "ServiceObjects"; sourceTree = ""; }; 83396BC71F7C3688000E256E /* Networking */ = { @@ -885,7 +885,7 @@ C443A4092315AA4D00145710 /* NetworkReporter.swift */, 831AAE2B20A9E4F600B46DBA /* Throttler.swift */, ); - path = "Service Objects"; + path = "ServiceObjects"; sourceTree = ""; }; B467790E24D8AECA00897F00 /* Frameworks */ = { @@ -1970,7 +1970,7 @@ repositoryURL = "https://github.com/LaunchDarkly/swift-eventsource.git"; requirement = { kind = upToNextMinorVersion; - minimumVersion = 1.1.0; + minimumVersion = 1.2.0; }; }; B4903D9624BD61B200F087C4 /* XCRemoteSwiftPackageReference "OHHTTPStubs" */ = { diff --git a/LaunchDarkly.xcworkspace/xcshareddata/swiftpm/Package.resolved b/LaunchDarkly.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved similarity index 94% rename from LaunchDarkly.xcworkspace/xcshareddata/swiftpm/Package.resolved rename to LaunchDarkly.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 9cf4a71c..d369acc5 100644 --- a/LaunchDarkly.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/LaunchDarkly.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -51,8 +51,8 @@ "repositoryURL": "https://github.com/LaunchDarkly/swift-eventsource.git", "state": { "branch": null, - "revision": "4f817e1a6ce5f8bc90e06b4f19dcd999db099210", - "version": "1.1.0" + "revision": "9e224016ec5dfda7d66e0f825152f97cbe44ccb8", + "version": "1.2.0" } } ] diff --git a/LaunchDarkly/LaunchDarkly/Models/DiagnosticEvent.swift b/LaunchDarkly/LaunchDarkly/Models/DiagnosticEvent.swift index 8100d43a..4f2e0b35 100644 --- a/LaunchDarkly/LaunchDarkly/Models/DiagnosticEvent.swift +++ b/LaunchDarkly/LaunchDarkly/Models/DiagnosticEvent.swift @@ -115,6 +115,7 @@ struct DiagnosticConfig: Codable { let maxCachedUsers: Int let mobileKeyCount: Int let diagnosticRecordingIntervalMillis: Int + let customHeaders: Bool init(config: LDConfig) { customBaseURI = config.baseUrl != LDConfig.Defaults.baseUrl @@ -135,5 +136,6 @@ struct DiagnosticConfig: Codable { maxCachedUsers = config.maxCachedUsers >= 0 ? config.maxCachedUsers : -1 mobileKeyCount = 1 + (config.getSecondaryMobileKeys().count) diagnosticRecordingIntervalMillis = Int(round(config.diagnosticRecordingInterval * 1_000)) + customHeaders = !config.additionalHeaders.isEmpty || config.headerDelegate != nil } } diff --git a/LaunchDarkly/LaunchDarkly/Models/LDConfig.swift b/LaunchDarkly/LaunchDarkly/Models/LDConfig.swift index c4edc0e3..3b748082 100644 --- a/LaunchDarkly/LaunchDarkly/Models/LDConfig.swift +++ b/LaunchDarkly/LaunchDarkly/Models/LDConfig.swift @@ -17,6 +17,19 @@ public enum LDStreamingMode { typealias MobileKey = String + +/** + A callback for dynamically setting http headers when connection & reconnecting to a stream + or on every poll request. This function should return a copy of the headers recieved with + any modifications or additions needed. Removing headers is discouraged as it may cause + requests to fail. + + - parameter url: The endpoint that is being connected to + - parameter headers: The default headers that would be used + - returns: The headers that will be used in the request + */ +public typealias RequestHeaderTransform = (_ url: URL, _ headers: [String: String]) -> [String: String] + /** Use LDConfig to configure the LDClient. When initialized, a LDConfig contains the default values which can be changed as needed. @@ -89,6 +102,9 @@ public struct LDConfig { /// The default additional headers that should be added to all HTTP requests from SDK components to LaunchDarkly services static let additionalHeaders: [String: String] = [:] + + /// a closure to allow dynamic changes of headers on connect & reconnect + static let headerDelegate: RequestHeaderTransform? = nil } /// Constants relevant to setting up an `LDConfig` @@ -238,6 +254,9 @@ public struct LDConfig { /// Additional headers that should be added to all HTTP requests from SDK components to LaunchDarkly services public var additionalHeaders: [String: String] = [:] + /// a closure to allow dynamic changes of headers on connect & reconnect + public var headerDelegate: RequestHeaderTransform? + /// LaunchDarkly defined minima for selected configurable items public let minima: Minima diff --git a/LaunchDarkly/LaunchDarkly/Networking/DarklyService.swift b/LaunchDarkly/LaunchDarkly/Networking/DarklyService.swift index 62fa5d28..74a1292d 100644 --- a/LaunchDarkly/LaunchDarkly/Networking/DarklyService.swift +++ b/LaunchDarkly/LaunchDarkly/Networking/DarklyService.swift @@ -80,6 +80,17 @@ final class DarklyService: DarklyServiceProvider { // MARK: Feature Flags + private func requestTask(with: URLRequest, + completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void + ) -> URLSessionDataTask { + // copying the request is needed because swift passes by const reference without any real way of changing that + var req = with + if let headerDelegate = config.headerDelegate { + req.allHTTPHeaderFields = headerDelegate(with.url!, req.allHTTPHeaderFields ?? [:]) + } + return self.session.dataTask(with: req, completionHandler: completionHandler) + } + func getFeatureFlags(useReport: Bool, completion: ServiceCompletionHandler?) { guard !config.mobileKey.isEmpty, let flagRequest = flagRequest(useReport: useReport) @@ -91,7 +102,7 @@ final class DarklyService: DarklyServiceProvider { } return } - let dataTask = self.session.dataTask(with: flagRequest) { [weak self] data, response, error in + let dataTask = requestTask(with: flagRequest) { [weak self] data, response, error in DispatchQueue.main.async { self?.processEtag(from: (data, response, error)) completion?((data, response, error)) @@ -166,7 +177,9 @@ final class DarklyService: DarklyServiceProvider { // MARK: Streaming - func createEventSource(useReport: Bool, handler: EventHandler, errorHandler: ConnectionErrorHandler?) -> DarklyStreamingProvider { + func createEventSource(useReport: Bool, + handler: EventHandler, + errorHandler: ConnectionErrorHandler?) -> DarklyStreamingProvider { if useReport { return serviceFactory.makeStreamingProvider(url: reportStreamRequestUrl, httpHeaders: httpHeaders.eventSourceHeaders, @@ -175,11 +188,13 @@ final class DarklyService: DarklyServiceProvider { .dictionaryValue(includePrivateAttributes: true, config: config) .jsonData, handler: handler, + delegate: config.headerDelegate, errorHandler: errorHandler) } return serviceFactory.makeStreamingProvider(url: getStreamRequestUrl, httpHeaders: httpHeaders.eventSourceHeaders, handler: handler, + delegate: config.headerDelegate, errorHandler: errorHandler) } @@ -206,7 +221,7 @@ final class DarklyService: DarklyServiceProvider { } return } - let dataTask = self.session.dataTask(with: eventRequest(eventDictionaries: eventDictionaries, payloadId: payloadId)) { (data, response, error) in + let dataTask = requestTask(with: eventRequest(eventDictionaries: eventDictionaries, payloadId: payloadId)) { (data, response, error) in completion?((data, response, error)) } dataTask.resume() @@ -232,7 +247,7 @@ final class DarklyService: DarklyServiceProvider { Log.debug(typeName(and: #function, appending: ": ") + "Aborting. No mobile key.") return } - let dataTask = self.session.dataTask(with: diagnosticRequest(diagnosticEvent: diagnosticEvent)) { data, response, error in + let dataTask = requestTask(with: diagnosticRequest(diagnosticEvent: diagnosticEvent)) { data, response, error in completion?((data, response, error)) } dataTask.resume() @@ -256,9 +271,7 @@ extension DarklyService: TypeIdentifying { } extension URLRequest { mutating func appendHeaders(_ newHeaders: [String: String]) { var headers = self.allHTTPHeaderFields ?? [:] - headers.merge(newHeaders) { _, newValue in - newValue - } + headers.merge(newHeaders) { $1 } self.allHTTPHeaderFields = headers } } diff --git a/LaunchDarkly/LaunchDarkly/Networking/HTTPHeaders.swift b/LaunchDarkly/LaunchDarkly/Networking/HTTPHeaders.swift index 8c97b6d1..e2669908 100644 --- a/LaunchDarkly/LaunchDarkly/Networking/HTTPHeaders.swift +++ b/LaunchDarkly/LaunchDarkly/Networking/HTTPHeaders.swift @@ -100,6 +100,6 @@ struct HTTPHeaders { } private func withAdditionalHeaders(_ headers: [String: String]) -> [String: String] { - headers.merging(additionalHeaders, uniquingKeysWith: { $1 }) + headers.merging(additionalHeaders) { $1 } } } diff --git a/LaunchDarkly/LaunchDarkly/Service Objects/Cache/CacheConverter.swift b/LaunchDarkly/LaunchDarkly/ServiceObjects/Cache/CacheConverter.swift similarity index 100% rename from LaunchDarkly/LaunchDarkly/Service Objects/Cache/CacheConverter.swift rename to LaunchDarkly/LaunchDarkly/ServiceObjects/Cache/CacheConverter.swift diff --git a/LaunchDarkly/LaunchDarkly/Service Objects/Cache/ConnectionInformationStore.swift b/LaunchDarkly/LaunchDarkly/ServiceObjects/Cache/ConnectionInformationStore.swift similarity index 100% rename from LaunchDarkly/LaunchDarkly/Service Objects/Cache/ConnectionInformationStore.swift rename to LaunchDarkly/LaunchDarkly/ServiceObjects/Cache/ConnectionInformationStore.swift diff --git a/LaunchDarkly/LaunchDarkly/Service Objects/Cache/DeprecatedCache.swift b/LaunchDarkly/LaunchDarkly/ServiceObjects/Cache/DeprecatedCache.swift similarity index 100% rename from LaunchDarkly/LaunchDarkly/Service Objects/Cache/DeprecatedCache.swift rename to LaunchDarkly/LaunchDarkly/ServiceObjects/Cache/DeprecatedCache.swift diff --git a/LaunchDarkly/LaunchDarkly/Service Objects/Cache/DeprecatedCacheModelV2.swift b/LaunchDarkly/LaunchDarkly/ServiceObjects/Cache/DeprecatedCacheModelV2.swift similarity index 100% rename from LaunchDarkly/LaunchDarkly/Service Objects/Cache/DeprecatedCacheModelV2.swift rename to LaunchDarkly/LaunchDarkly/ServiceObjects/Cache/DeprecatedCacheModelV2.swift diff --git a/LaunchDarkly/LaunchDarkly/Service Objects/Cache/DeprecatedCacheModelV3.swift b/LaunchDarkly/LaunchDarkly/ServiceObjects/Cache/DeprecatedCacheModelV3.swift similarity index 100% rename from LaunchDarkly/LaunchDarkly/Service Objects/Cache/DeprecatedCacheModelV3.swift rename to LaunchDarkly/LaunchDarkly/ServiceObjects/Cache/DeprecatedCacheModelV3.swift diff --git a/LaunchDarkly/LaunchDarkly/Service Objects/Cache/DeprecatedCacheModelV4.swift b/LaunchDarkly/LaunchDarkly/ServiceObjects/Cache/DeprecatedCacheModelV4.swift similarity index 100% rename from LaunchDarkly/LaunchDarkly/Service Objects/Cache/DeprecatedCacheModelV4.swift rename to LaunchDarkly/LaunchDarkly/ServiceObjects/Cache/DeprecatedCacheModelV4.swift diff --git a/LaunchDarkly/LaunchDarkly/Service Objects/Cache/DeprecatedCacheModelV5.swift b/LaunchDarkly/LaunchDarkly/ServiceObjects/Cache/DeprecatedCacheModelV5.swift similarity index 100% rename from LaunchDarkly/LaunchDarkly/Service Objects/Cache/DeprecatedCacheModelV5.swift rename to LaunchDarkly/LaunchDarkly/ServiceObjects/Cache/DeprecatedCacheModelV5.swift diff --git a/LaunchDarkly/LaunchDarkly/Service Objects/Cache/DiagnosticCache.swift b/LaunchDarkly/LaunchDarkly/ServiceObjects/Cache/DiagnosticCache.swift similarity index 100% rename from LaunchDarkly/LaunchDarkly/Service Objects/Cache/DiagnosticCache.swift rename to LaunchDarkly/LaunchDarkly/ServiceObjects/Cache/DiagnosticCache.swift diff --git a/LaunchDarkly/LaunchDarkly/Service Objects/Cache/KeyedValueCache.swift b/LaunchDarkly/LaunchDarkly/ServiceObjects/Cache/KeyedValueCache.swift similarity index 100% rename from LaunchDarkly/LaunchDarkly/Service Objects/Cache/KeyedValueCache.swift rename to LaunchDarkly/LaunchDarkly/ServiceObjects/Cache/KeyedValueCache.swift diff --git a/LaunchDarkly/LaunchDarkly/Service Objects/Cache/UserEnvironmentFlagCache.swift b/LaunchDarkly/LaunchDarkly/ServiceObjects/Cache/UserEnvironmentFlagCache.swift similarity index 100% rename from LaunchDarkly/LaunchDarkly/Service Objects/Cache/UserEnvironmentFlagCache.swift rename to LaunchDarkly/LaunchDarkly/ServiceObjects/Cache/UserEnvironmentFlagCache.swift diff --git a/LaunchDarkly/LaunchDarkly/Service Objects/ClientServiceFactory.swift b/LaunchDarkly/LaunchDarkly/ServiceObjects/ClientServiceFactory.swift similarity index 84% rename from LaunchDarkly/LaunchDarkly/Service Objects/ClientServiceFactory.swift rename to LaunchDarkly/LaunchDarkly/ServiceObjects/ClientServiceFactory.swift index 4a0fd2cb..ab6d81e3 100644 --- a/LaunchDarkly/LaunchDarkly/Service Objects/ClientServiceFactory.swift +++ b/LaunchDarkly/LaunchDarkly/ServiceObjects/ClientServiceFactory.swift @@ -23,8 +23,8 @@ protocol ClientServiceCreating { func makeFlagChangeNotifier() -> FlagChangeNotifying func makeEventReporter(config: LDConfig, service: DarklyServiceProvider) -> EventReporting func makeEventReporter(config: LDConfig, service: DarklyServiceProvider, onSyncComplete: EventSyncCompleteClosure?) -> EventReporting - func makeStreamingProvider(url: URL, httpHeaders: [String: String], handler: EventHandler, errorHandler: ConnectionErrorHandler?) -> DarklyStreamingProvider - func makeStreamingProvider(url: URL, httpHeaders: [String: String], connectMethod: String?, connectBody: Data?, handler: EventHandler, errorHandler: ConnectionErrorHandler?) -> DarklyStreamingProvider + func makeStreamingProvider(url: URL, httpHeaders: [String: String], handler: EventHandler, delegate: RequestHeaderTransform?, errorHandler: ConnectionErrorHandler?) -> DarklyStreamingProvider + func makeStreamingProvider(url: URL, httpHeaders: [String: String], connectMethod: String?, connectBody: Data?, handler: EventHandler, delegate: RequestHeaderTransform?, errorHandler: ConnectionErrorHandler?) -> DarklyStreamingProvider func makeEnvironmentReporter() -> EnvironmentReporting func makeThrottler(maxDelay: TimeInterval, environmentReporter: EnvironmentReporting) -> Throttling func makeErrorNotifier() -> ErrorNotifying @@ -83,17 +83,29 @@ final class ClientServiceFactory: ClientServiceCreating { EventReporter(config: config, service: service, onSyncComplete: onSyncComplete) } - func makeStreamingProvider(url: URL, httpHeaders: [String: String], handler: EventHandler, errorHandler: ConnectionErrorHandler?) -> DarklyStreamingProvider { + func makeStreamingProvider(url: URL, + httpHeaders: [String: String], + handler: EventHandler, + delegate: RequestHeaderTransform?, + errorHandler: ConnectionErrorHandler?) -> DarklyStreamingProvider { var config: EventSource.Config = EventSource.Config(handler: handler, url: url) config.headers = httpHeaders + config.headerTransform = { delegate?(url, $0) ?? $0 } if let errorHandler = errorHandler { config.connectionErrorHandler = errorHandler } return EventSource(config: config) } - func makeStreamingProvider(url: URL, httpHeaders: [String: String], connectMethod: String?, connectBody: Data?, handler: EventHandler, errorHandler: ConnectionErrorHandler?) -> DarklyStreamingProvider { + func makeStreamingProvider(url: URL, + httpHeaders: [String: String], + connectMethod: String?, + connectBody: Data?, + handler: EventHandler, + delegate: RequestHeaderTransform?, + errorHandler: ConnectionErrorHandler?) -> DarklyStreamingProvider { var config: EventSource.Config = EventSource.Config(handler: handler, url: url) + config.headerTransform = { delegate?(url, $0) ?? $0 } config.headers = httpHeaders if let errorHandler = errorHandler { config.connectionErrorHandler = errorHandler diff --git a/LaunchDarkly/LaunchDarkly/Service Objects/CwlSysctl.swift b/LaunchDarkly/LaunchDarkly/ServiceObjects/CwlSysctl.swift similarity index 100% rename from LaunchDarkly/LaunchDarkly/Service Objects/CwlSysctl.swift rename to LaunchDarkly/LaunchDarkly/ServiceObjects/CwlSysctl.swift diff --git a/LaunchDarkly/LaunchDarkly/Service Objects/DiagnosticReporter.swift b/LaunchDarkly/LaunchDarkly/ServiceObjects/DiagnosticReporter.swift similarity index 100% rename from LaunchDarkly/LaunchDarkly/Service Objects/DiagnosticReporter.swift rename to LaunchDarkly/LaunchDarkly/ServiceObjects/DiagnosticReporter.swift diff --git a/LaunchDarkly/LaunchDarkly/Service Objects/EnvironmentReporter.swift b/LaunchDarkly/LaunchDarkly/ServiceObjects/EnvironmentReporter.swift similarity index 100% rename from LaunchDarkly/LaunchDarkly/Service Objects/EnvironmentReporter.swift rename to LaunchDarkly/LaunchDarkly/ServiceObjects/EnvironmentReporter.swift diff --git a/LaunchDarkly/LaunchDarkly/Service Objects/ErrorNotifier.swift b/LaunchDarkly/LaunchDarkly/ServiceObjects/ErrorNotifier.swift similarity index 100% rename from LaunchDarkly/LaunchDarkly/Service Objects/ErrorNotifier.swift rename to LaunchDarkly/LaunchDarkly/ServiceObjects/ErrorNotifier.swift diff --git a/LaunchDarkly/LaunchDarkly/Service Objects/EventReporter.swift b/LaunchDarkly/LaunchDarkly/ServiceObjects/EventReporter.swift similarity index 100% rename from LaunchDarkly/LaunchDarkly/Service Objects/EventReporter.swift rename to LaunchDarkly/LaunchDarkly/ServiceObjects/EventReporter.swift diff --git a/LaunchDarkly/LaunchDarkly/Service Objects/FlagChangeNotifier.swift b/LaunchDarkly/LaunchDarkly/ServiceObjects/FlagChangeNotifier.swift similarity index 100% rename from LaunchDarkly/LaunchDarkly/Service Objects/FlagChangeNotifier.swift rename to LaunchDarkly/LaunchDarkly/ServiceObjects/FlagChangeNotifier.swift diff --git a/LaunchDarkly/LaunchDarkly/Service Objects/FlagStore.swift b/LaunchDarkly/LaunchDarkly/ServiceObjects/FlagStore.swift similarity index 100% rename from LaunchDarkly/LaunchDarkly/Service Objects/FlagStore.swift rename to LaunchDarkly/LaunchDarkly/ServiceObjects/FlagStore.swift diff --git a/LaunchDarkly/LaunchDarkly/Service Objects/FlagSynchronizer.swift b/LaunchDarkly/LaunchDarkly/ServiceObjects/FlagSynchronizer.swift similarity index 98% rename from LaunchDarkly/LaunchDarkly/Service Objects/FlagSynchronizer.swift rename to LaunchDarkly/LaunchDarkly/ServiceObjects/FlagSynchronizer.swift index 661cacfe..dc793f1f 100644 --- a/LaunchDarkly/LaunchDarkly/Service Objects/FlagSynchronizer.swift +++ b/LaunchDarkly/LaunchDarkly/ServiceObjects/FlagSynchronizer.swift @@ -87,7 +87,11 @@ class FlagSynchronizer: LDFlagSynchronizing, EventHandler { private var syncQueue = DispatchQueue(label: Constants.queueName, qos: .utility) private var eventSourceStarted: Date? - init(streamingMode: LDStreamingMode, pollingInterval: TimeInterval, useReport: Bool, service: DarklyServiceProvider, onSyncComplete: FlagSyncCompleteClosure?) { + init(streamingMode: LDStreamingMode, + pollingInterval: TimeInterval, + useReport: Bool, + service: DarklyServiceProvider, + onSyncComplete: FlagSyncCompleteClosure?) { Log.debug(FlagSynchronizer.typeName(and: #function) + "streamingMode: \(streamingMode), " + "pollingInterval: \(pollingInterval), " + "useReport: \(useReport)") self.streamingMode = streamingMode self.pollingInterval = pollingInterval diff --git a/LaunchDarkly/LaunchDarkly/Service Objects/LDTimer.swift b/LaunchDarkly/LaunchDarkly/ServiceObjects/LDTimer.swift similarity index 100% rename from LaunchDarkly/LaunchDarkly/Service Objects/LDTimer.swift rename to LaunchDarkly/LaunchDarkly/ServiceObjects/LDTimer.swift diff --git a/LaunchDarkly/LaunchDarkly/Service Objects/Log.swift b/LaunchDarkly/LaunchDarkly/ServiceObjects/Log.swift similarity index 100% rename from LaunchDarkly/LaunchDarkly/Service Objects/Log.swift rename to LaunchDarkly/LaunchDarkly/ServiceObjects/Log.swift diff --git a/LaunchDarkly/LaunchDarkly/Service Objects/NetworkReporter.swift b/LaunchDarkly/LaunchDarkly/ServiceObjects/NetworkReporter.swift similarity index 100% rename from LaunchDarkly/LaunchDarkly/Service Objects/NetworkReporter.swift rename to LaunchDarkly/LaunchDarkly/ServiceObjects/NetworkReporter.swift diff --git a/LaunchDarkly/LaunchDarkly/Service Objects/Throttler.swift b/LaunchDarkly/LaunchDarkly/ServiceObjects/Throttler.swift similarity index 100% rename from LaunchDarkly/LaunchDarkly/Service Objects/Throttler.swift rename to LaunchDarkly/LaunchDarkly/ServiceObjects/Throttler.swift diff --git a/LaunchDarkly/LaunchDarklyTests/Mocks/ClientServiceMockFactory.swift b/LaunchDarkly/LaunchDarklyTests/Mocks/ClientServiceMockFactory.swift index 142f467a..b206007d 100644 --- a/LaunchDarkly/LaunchDarklyTests/Mocks/ClientServiceMockFactory.swift +++ b/LaunchDarkly/LaunchDarklyTests/Mocks/ClientServiceMockFactory.swift @@ -90,16 +90,22 @@ final class ClientServiceMockFactory: ClientServiceCreating { } var makeStreamingProviderCallCount = 0 - var makeStreamingProviderReceivedArguments: (url: URL, httpHeaders: [String: String], connectMethod: String?, connectBody: Data?, handler: EventHandler, errorHandler: ConnectionErrorHandler?)? - func makeStreamingProvider(url: URL, httpHeaders: [String: String], handler: EventHandler, errorHandler: ConnectionErrorHandler?) -> DarklyStreamingProvider { + var makeStreamingProviderReceivedArguments: (url: URL, + httpHeaders: [String: String], + connectMethod: String?, + connectBody: Data?, + handler: EventHandler, + delegate: RequestHeaderTransform?, + errorHandler: ConnectionErrorHandler?)? + func makeStreamingProvider(url: URL, httpHeaders: [String: String], handler: EventHandler, delegate: RequestHeaderTransform?, errorHandler: ConnectionErrorHandler?) -> DarklyStreamingProvider { makeStreamingProviderCallCount += 1 - makeStreamingProviderReceivedArguments = (url, httpHeaders, nil, nil, handler, errorHandler) + makeStreamingProviderReceivedArguments = (url, httpHeaders, nil, nil, handler, delegate, errorHandler) return DarklyStreamingProviderMock() } - func makeStreamingProvider(url: URL, httpHeaders: [String: String], connectMethod: String?, connectBody: Data?, handler: EventHandler, errorHandler: ConnectionErrorHandler?) -> DarklyStreamingProvider { + func makeStreamingProvider(url: URL, httpHeaders: [String: String], connectMethod: String?, connectBody: Data?, handler: EventHandler, delegate: RequestHeaderTransform?, errorHandler: ConnectionErrorHandler?) -> DarklyStreamingProvider { makeStreamingProviderCallCount += 1 - makeStreamingProviderReceivedArguments = (url, httpHeaders, connectMethod, connectBody, handler, errorHandler) + makeStreamingProviderReceivedArguments = (url, httpHeaders, connectMethod, connectBody, handler, delegate, errorHandler) return DarklyStreamingProviderMock() } diff --git a/LaunchDarkly/LaunchDarklyTests/Models/DiagnosticEventSpec.swift b/LaunchDarkly/LaunchDarklyTests/Models/DiagnosticEventSpec.swift index 24d3dc11..0697e148 100644 --- a/LaunchDarkly/LaunchDarklyTests/Models/DiagnosticEventSpec.swift +++ b/LaunchDarkly/LaunchDarklyTests/Models/DiagnosticEventSpec.swift @@ -238,6 +238,7 @@ final class DiagnosticEventSpec: QuickSpec { expect(diagnosticConfig.maxCachedUsers) == 5 expect(diagnosticConfig.mobileKeyCount) == 1 expect(diagnosticConfig.diagnosticRecordingIntervalMillis) == 900_000 + expect(diagnosticConfig.customHeaders) == false } } context("init with custom config") { @@ -261,6 +262,7 @@ final class DiagnosticEventSpec: QuickSpec { expect(diagnosticConfig.maxCachedUsers) == -1 expect(diagnosticConfig.mobileKeyCount) == 3 expect(diagnosticConfig.diagnosticRecordingIntervalMillis) == 600_000 + expect(diagnosticConfig.customHeaders) == false } } var diagnosticConfig: DiagnosticConfig! @@ -273,7 +275,7 @@ final class DiagnosticEventSpec: QuickSpec { context("using \(desc) encoding") { it("encodes correct values to keys") { let decoded = self.loadAndRestoreRaw(scheme, diagnosticConfig) - expect(decoded.count) == 17 + expect(decoded.count) == 18 expect((decoded["customBaseURI"] as! Bool)) == diagnosticConfig.customBaseURI expect((decoded["customEventsURI"] as! Bool)) == diagnosticConfig.customEventsURI expect((decoded["customStreamURI"] as! Bool)) == diagnosticConfig.customStreamURI diff --git a/LaunchDarkly/LaunchDarklyTests/Service Objects/Cache/CacheConverterSpec.swift b/LaunchDarkly/LaunchDarklyTests/ServiceObjects/Cache/CacheConverterSpec.swift similarity index 100% rename from LaunchDarkly/LaunchDarklyTests/Service Objects/Cache/CacheConverterSpec.swift rename to LaunchDarkly/LaunchDarklyTests/ServiceObjects/Cache/CacheConverterSpec.swift diff --git a/LaunchDarkly/LaunchDarklyTests/Service Objects/Cache/DeprecatedCacheModelV2Spec.swift b/LaunchDarkly/LaunchDarklyTests/ServiceObjects/Cache/DeprecatedCacheModelV2Spec.swift similarity index 100% rename from LaunchDarkly/LaunchDarklyTests/Service Objects/Cache/DeprecatedCacheModelV2Spec.swift rename to LaunchDarkly/LaunchDarklyTests/ServiceObjects/Cache/DeprecatedCacheModelV2Spec.swift diff --git a/LaunchDarkly/LaunchDarklyTests/Service Objects/Cache/DeprecatedCacheModelV3Spec.swift b/LaunchDarkly/LaunchDarklyTests/ServiceObjects/Cache/DeprecatedCacheModelV3Spec.swift similarity index 100% rename from LaunchDarkly/LaunchDarklyTests/Service Objects/Cache/DeprecatedCacheModelV3Spec.swift rename to LaunchDarkly/LaunchDarklyTests/ServiceObjects/Cache/DeprecatedCacheModelV3Spec.swift diff --git a/LaunchDarkly/LaunchDarklyTests/Service Objects/Cache/DeprecatedCacheModelV4Spec.swift b/LaunchDarkly/LaunchDarklyTests/ServiceObjects/Cache/DeprecatedCacheModelV4Spec.swift similarity index 100% rename from LaunchDarkly/LaunchDarklyTests/Service Objects/Cache/DeprecatedCacheModelV4Spec.swift rename to LaunchDarkly/LaunchDarklyTests/ServiceObjects/Cache/DeprecatedCacheModelV4Spec.swift diff --git a/LaunchDarkly/LaunchDarklyTests/Service Objects/Cache/DeprecatedCacheModelV5Spec.swift b/LaunchDarkly/LaunchDarklyTests/ServiceObjects/Cache/DeprecatedCacheModelV5Spec.swift similarity index 100% rename from LaunchDarkly/LaunchDarklyTests/Service Objects/Cache/DeprecatedCacheModelV5Spec.swift rename to LaunchDarkly/LaunchDarklyTests/ServiceObjects/Cache/DeprecatedCacheModelV5Spec.swift diff --git a/LaunchDarkly/LaunchDarklyTests/Service Objects/Cache/DiagnosticCacheSpec.swift b/LaunchDarkly/LaunchDarklyTests/ServiceObjects/Cache/DiagnosticCacheSpec.swift similarity index 100% rename from LaunchDarkly/LaunchDarklyTests/Service Objects/Cache/DiagnosticCacheSpec.swift rename to LaunchDarkly/LaunchDarklyTests/ServiceObjects/Cache/DiagnosticCacheSpec.swift diff --git a/LaunchDarkly/LaunchDarklyTests/Service Objects/Cache/KeyedValueCacheSpec.swift b/LaunchDarkly/LaunchDarklyTests/ServiceObjects/Cache/KeyedValueCacheSpec.swift similarity index 100% rename from LaunchDarkly/LaunchDarklyTests/Service Objects/Cache/KeyedValueCacheSpec.swift rename to LaunchDarkly/LaunchDarklyTests/ServiceObjects/Cache/KeyedValueCacheSpec.swift diff --git a/LaunchDarkly/LaunchDarklyTests/Service Objects/Cache/UserEnvironmentFlagCacheSpec.swift b/LaunchDarkly/LaunchDarklyTests/ServiceObjects/Cache/UserEnvironmentFlagCacheSpec.swift similarity index 100% rename from LaunchDarkly/LaunchDarklyTests/Service Objects/Cache/UserEnvironmentFlagCacheSpec.swift rename to LaunchDarkly/LaunchDarklyTests/ServiceObjects/Cache/UserEnvironmentFlagCacheSpec.swift diff --git a/LaunchDarkly/LaunchDarklyTests/Service Objects/EnvironmentReporterSpec.swift b/LaunchDarkly/LaunchDarklyTests/ServiceObjects/EnvironmentReporterSpec.swift similarity index 100% rename from LaunchDarkly/LaunchDarklyTests/Service Objects/EnvironmentReporterSpec.swift rename to LaunchDarkly/LaunchDarklyTests/ServiceObjects/EnvironmentReporterSpec.swift diff --git a/LaunchDarkly/LaunchDarklyTests/Service Objects/ErrorNotifierSpec.swift b/LaunchDarkly/LaunchDarklyTests/ServiceObjects/ErrorNotifierSpec.swift similarity index 100% rename from LaunchDarkly/LaunchDarklyTests/Service Objects/ErrorNotifierSpec.swift rename to LaunchDarkly/LaunchDarklyTests/ServiceObjects/ErrorNotifierSpec.swift diff --git a/LaunchDarkly/LaunchDarklyTests/Service Objects/EventReporterSpec.swift b/LaunchDarkly/LaunchDarklyTests/ServiceObjects/EventReporterSpec.swift similarity index 100% rename from LaunchDarkly/LaunchDarklyTests/Service Objects/EventReporterSpec.swift rename to LaunchDarkly/LaunchDarklyTests/ServiceObjects/EventReporterSpec.swift diff --git a/LaunchDarkly/LaunchDarklyTests/Service Objects/FlagChangeNotifierSpec.swift b/LaunchDarkly/LaunchDarklyTests/ServiceObjects/FlagChangeNotifierSpec.swift similarity index 100% rename from LaunchDarkly/LaunchDarklyTests/Service Objects/FlagChangeNotifierSpec.swift rename to LaunchDarkly/LaunchDarklyTests/ServiceObjects/FlagChangeNotifierSpec.swift diff --git a/LaunchDarkly/LaunchDarklyTests/Service Objects/FlagStoreSpec.swift b/LaunchDarkly/LaunchDarklyTests/ServiceObjects/FlagStoreSpec.swift similarity index 100% rename from LaunchDarkly/LaunchDarklyTests/Service Objects/FlagStoreSpec.swift rename to LaunchDarkly/LaunchDarklyTests/ServiceObjects/FlagStoreSpec.swift diff --git a/LaunchDarkly/LaunchDarklyTests/Service Objects/FlagSynchronizerSpec.swift b/LaunchDarkly/LaunchDarklyTests/ServiceObjects/FlagSynchronizerSpec.swift similarity index 100% rename from LaunchDarkly/LaunchDarklyTests/Service Objects/FlagSynchronizerSpec.swift rename to LaunchDarkly/LaunchDarklyTests/ServiceObjects/FlagSynchronizerSpec.swift diff --git a/LaunchDarkly/LaunchDarklyTests/Service Objects/LDTimerSpec.swift b/LaunchDarkly/LaunchDarklyTests/ServiceObjects/LDTimerSpec.swift similarity index 100% rename from LaunchDarkly/LaunchDarklyTests/Service Objects/LDTimerSpec.swift rename to LaunchDarkly/LaunchDarklyTests/ServiceObjects/LDTimerSpec.swift diff --git a/LaunchDarkly/LaunchDarklyTests/Service Objects/SynchronizingErrorSpec.swift b/LaunchDarkly/LaunchDarklyTests/ServiceObjects/SynchronizingErrorSpec.swift similarity index 100% rename from LaunchDarkly/LaunchDarklyTests/Service Objects/SynchronizingErrorSpec.swift rename to LaunchDarkly/LaunchDarklyTests/ServiceObjects/SynchronizingErrorSpec.swift diff --git a/LaunchDarkly/LaunchDarklyTests/Service Objects/ThrottlerSpec.swift b/LaunchDarkly/LaunchDarklyTests/ServiceObjects/ThrottlerSpec.swift similarity index 100% rename from LaunchDarkly/LaunchDarklyTests/Service Objects/ThrottlerSpec.swift rename to LaunchDarkly/LaunchDarklyTests/ServiceObjects/ThrottlerSpec.swift diff --git a/Package.resolved b/Package.resolved index 9cf4a71c..d369acc5 100644 --- a/Package.resolved +++ b/Package.resolved @@ -51,8 +51,8 @@ "repositoryURL": "https://github.com/LaunchDarkly/swift-eventsource.git", "state": { "branch": null, - "revision": "4f817e1a6ce5f8bc90e06b4f19dcd999db099210", - "version": "1.1.0" + "revision": "9e224016ec5dfda7d66e0f825152f97cbe44ccb8", + "version": "1.2.0" } } ] diff --git a/Package.swift b/Package.swift index ec2873bb..ae92ce99 100644 --- a/Package.swift +++ b/Package.swift @@ -19,7 +19,7 @@ let package = Package( .package(url: "https://github.com/AliSoftware/OHHTTPStubs.git", .upToNextMinor(from: "9.0.0")), .package(url: "https://github.com/Quick/Quick.git", .upToNextMinor(from: "3.0.0")), .package(url: "https://github.com/Quick/Nimble.git", .upToNextMinor(from: "9.0.0")), - .package(url: "https://github.com/LaunchDarkly/swift-eventsource.git", .upToNextMinor(from: "1.1.0")) + .package(url: "https://github.com/LaunchDarkly/swift-eventsource.git", .upToNextMinor(from: "1.2.0")) ], targets: [ .target( @@ -32,6 +32,6 @@ let package = Package( dependencies: ["LaunchDarkly", "OHHTTPStubsSwift", "Quick", "Nimble"], path: "LaunchDarkly", exclude: ["LaunchDarklyTests/Info.plist", "LaunchDarklyTests/.swiftlint.yml"], - sources: ["GeneratedCode", "LaunchDarklyTests"]) + sources: ["GeneratedCode", "LaunchDarklyTests"]), ], swiftLanguageVersions: [.v5])