Skip to content

Commit e07db95

Browse files
committed
Add customHeaders option
1 parent 283d3a9 commit e07db95

File tree

5 files changed

+67
-1
lines changed

5 files changed

+67
-1
lines changed

Sources/GOFeatureFlag/controller/goff_api.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ class GoFeatureFlagAPI {
4444
"application/json",
4545
forHTTPHeaderField: "Content-Type"
4646
)
47+
if let headers = self.options.customHeaders {
48+
for (key, value) in headers {
49+
request.SetValue(value, forHTTPHeaderField: key)
50+
}
51+
}
4752
if let apiKey = self.options.apiKey {
4853
request.setValue("Bearer \(apiKey)", forHTTPHeaderField:"Authorization")
4954
}

Sources/GOFeatureFlag/options.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ public struct GoFeatureFlagProviderOptions {
2020
* Default: null
2121
*/
2222
public var apiKey: String?
23+
/**
24+
* (optional) custom headers to be sent for every HTTP request.
25+
* default: empty
26+
*/
27+
public var customHeaders: [String:String]? = [:]
2328
/**
2429
* (optional) interval time we publish statistics collection data to the proxy.
2530
* The parameter is used only if the cache is enabled, otherwise the collection of the data is done directly
@@ -42,12 +47,14 @@ public struct GoFeatureFlagProviderOptions {
4247
endpoint: String,
4348
pollInterval: TimeInterval = 60,
4449
apiKey: String? = nil,
50+
customHeaders: [String:String]? = [:],
4551
dataFlushInterval: TimeInterval = 600,
4652
exporterMetadata: [String:ExporterMetadataValue]? = [:],
4753
networkService: NetworkingService? = URLSession.shared) {
4854
self.endpoint = endpoint
4955
self.pollInterval = pollInterval
5056
self.apiKey = apiKey
57+
self.customHeaders = customHeaders
5158
self.networkService = networkService
5259
self.dataCollectorInterval = dataFlushInterval
5360
self.exporterMetadata = exporterMetadata

Sources/GOFeatureFlag/provider.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public final class GoFeatureFlagProvider: FeatureProvider {
2020
networkService = netSer
2121
}
2222

23-
var headers: [String:String] = [:]
23+
var headers: [String:String] = options.customHeaders ?? [:]
2424
if let apiKey = options.apiKey {
2525
headers["Authorization"] = "Bearer \(apiKey)"
2626
}

Tests/GOFeatureFlagTests/goff_api_tests.swift

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,4 +203,29 @@ class GoffApiTests: XCTestCase {
203203
XCTFail("Expected GoFeatureFlagError.noEventToSend but got a different error: \(error).")
204204
}
205205
}
206+
207+
func testShouldSendCustomHeaders() async throws{
208+
let mockService = MockNetworkingService(mockStatus: 200)
209+
let options = GeFeatureFlagProviderOptions(
210+
endpoint: "http://localhost:1031/",
211+
customHeaders: ["X-Custom-Headers": "custom-value"]
212+
)
213+
let goffAPI = GoFeatureFlagAPI(networkingService: mockService, options: options)
214+
215+
let events: [FeatureEvent] = [
216+
FeatureEvent(kind: "feature", userKey: "981f2662-1fb4-4732-ac6d-8399d9205aa9", creationDate: Int64(Date().timeIntervalSince1970),
217+
key: "flag-1", variation: "enabled", value: JSONValue.bool(true), default: false, version: nil, source: "PROVIDER_CACHE")
218+
]
219+
220+
do {
221+
_ = try await goffAPI.postDataCollector(events: events)
222+
guard let request = mockService.requests.last else {
223+
XCTFail("No request captured")
224+
return
225+
}
226+
XCTAssertEqual("custom-value", request.allHTTPHeaderFields?["X-Custom-Header"])
227+
} catch {
228+
XCTFail("exception thrown when doing the evaluation: \(error)")
229+
}
230+
}
206231
}

Tests/GOFeatureFlagTests/provider_tests.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,4 +204,33 @@ class GoFeatureFlagProviderTests: XCTestCase {
204204
XCTAssertEqual(2, mockNetworkService.dataCollectorCallCounter)
205205
XCTAssertEqual(6, mockNetworkService.dataCollectorEventCounter)
206206
}
207+
208+
func testProviderCustomHeaders() async {
209+
let mockNetworkService = MockNetworkingService(mockStatus: 200)
210+
let provider = GoFeatureFlagProvider(
211+
options: GoFeatureFlagProviderOptions(
212+
endpoint: "https://localhost:1031",
213+
apiKey: "apiKey1"
214+
customHeaders: [
215+
"X-Custom-Header": "custom-value",
216+
"Authorization": "Bearer custom" // should be overwritten by apiKey
217+
]
218+
networkService: mockNetworkService
219+
)
220+
)
221+
let evaluationCtx = MutableContext(targetingKey: "ede04e44-463d-40d1-8fc0-b1d6855578d0")
222+
let api = OpenFeatureAPI()
223+
await api.setProviderAndWait(provider: provider, initialContext: evaluationCtx)
224+
let client = api.getClient()
225+
226+
_ = client.getBooleanDetails(key: "my-flag", defaultValue: false)
227+
228+
guard let request = mockNetworkService.requests.last else {
229+
XCTFail("No request captured")
230+
return
231+
}
232+
233+
XCTAssertEqual("custom-value", request.allHTTPHeaderFields?["X-Custom-Header"])
234+
XCTAssertEqual("Bearer apiKey1", request.allHTTPHeaderFields?["Authorization"])
235+
}
207236
}

0 commit comments

Comments
 (0)