Skip to content

Commit f6e664e

Browse files
committed
Add CustomHeaders option
Signed-off-by: Olivier Laviale <olivier.laviale@gmail.com>
1 parent c7e5b60 commit f6e664e

File tree

5 files changed

+36
-5
lines changed

5 files changed

+36
-5
lines changed

providers/go-feature-flag/pkg/controller/goff_api.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ type GoFeatureFlagApiOptions struct {
2222
// (This feature is available only if you are using GO Feature Flag relay proxy v1.7.0 or above)
2323
// Default: null
2424
APIKey string
25+
// CustomHeaders (optional) allows setting custom headers for every HTTP request.
26+
// Default: null
27+
CustomHeaders map[string]string
2528
// ExporterMetadata (optional) If we set metadata, it will be sent with every data collection requests along with the events.
2629
ExporterMetadata map[string]any
2730
}
@@ -61,6 +64,9 @@ func (g *GoFeatureFlagAPI) CollectData(events []model.FeatureEvent) error {
6164
if g.options.APIKey != "" {
6265
req.Header.Set(AuthorizationHeader, BearerPrefix+g.options.APIKey)
6366
}
67+
for k, v := range g.options.CustomHeaders {
68+
req.Header.Set(k, v)
69+
}
6470

6571
response, err := g.getHttpClient().Do(req)
6672
if err != nil {
@@ -87,6 +93,9 @@ func (g *GoFeatureFlagAPI) ConfigurationHasChanged() (ConfigurationChangeStatus,
8793
if g.options.APIKey != "" {
8894
req.Header.Set(AuthorizationHeader, BearerPrefix+g.options.APIKey)
8995
}
96+
for k, v := range g.options.CustomHeaders {
97+
req.Header.Set(k, v)
98+
}
9099
if g.configChangeEtag != "" {
91100
req.Header.Set(IfNoneMatchHeader, g.configChangeEtag)
92101
}

providers/go-feature-flag/pkg/controller/goff_api_test.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ func Test_CollectDataAPI(t *testing.T) {
3030
options: controller.GoFeatureFlagApiOptions{
3131
Endpoint: "http://localhost:1031",
3232
APIKey: "",
33+
CustomHeaders: map[string]string{"User-Agent": "goff-sdk-tests"},
3334
ExporterMetadata: map[string]any{"openfeature": true, "provider": "go"},
3435
},
3536
events: []model.FeatureEvent{
@@ -67,6 +68,7 @@ func Test_CollectDataAPI(t *testing.T) {
6768
wantHeaders: func() http.Header {
6869
headers := http.Header{}
6970
headers.Set(controller.ContentTypeHeader, controller.ApplicationJson)
71+
headers.Set("User-Agent", "goff-sdk-tests")
7072
return headers
7173
}(),
7274
wantReqBody: "{\"events\":[{\"kind\":\"feature\",\"contextKind\":\"user\",\"userKey\":\"ABCD\",\"creationDate\":1722266324,\"key\":\"random-key\",\"variation\":\"variationA\",\"value\":\"YO\",\"default\":false,\"version\":\"\",\"source\":\"SERVER\"},{\"kind\":\"feature\",\"contextKind\":\"user\",\"userKey\":\"EFGH\",\"creationDate\":1722266324,\"key\":\"random-key\",\"variation\":\"variationA\",\"value\":\"YO\",\"default\":false,\"version\":\"\",\"source\":\"SERVER\"}],\"meta\":{\"openfeature\":true,\"provider\":\"go\"}}",
@@ -77,6 +79,7 @@ func Test_CollectDataAPI(t *testing.T) {
7779
options: controller.GoFeatureFlagApiOptions{
7880
Endpoint: "http://localhost:1031",
7981
APIKey: "my-key",
82+
CustomHeaders: map[string]string{"User-Agent": "goff-sdk-tests"},
8083
ExporterMetadata: map[string]any{"openfeature": true, "provider": "go"},
8184
},
8285
events: []model.FeatureEvent{
@@ -115,6 +118,7 @@ func Test_CollectDataAPI(t *testing.T) {
115118
headers := http.Header{}
116119
headers.Set(controller.ContentTypeHeader, controller.ApplicationJson)
117120
headers.Set(controller.AuthorizationHeader, controller.BearerPrefix+"my-key")
121+
headers.Set("User-Agent", "goff-sdk-tests")
118122
return headers
119123
}(),
120124
wantReqBody: "{\"events\":[{\"kind\":\"feature\",\"contextKind\":\"user\",\"userKey\":\"ABCD\",\"creationDate\":1722266324,\"key\":\"random-key\",\"variation\":\"variationA\",\"value\":\"YO\",\"default\":false,\"version\":\"\",\"source\":\"SERVER\"},{\"kind\":\"feature\",\"contextKind\":\"user\",\"userKey\":\"EFGH\",\"creationDate\":1722266324,\"key\":\"random-key\",\"variation\":\"variationA\",\"value\":\"YO\",\"default\":false,\"version\":\"\",\"source\":\"SERVER\"}],\"meta\":{\"openfeature\":true,\"provider\":\"go\"}}",
@@ -181,13 +185,15 @@ func Test_ConfigurationHasChanged(t *testing.T) {
181185
}}
182186
client := &http.Client{Transport: &mrt}
183187
options := controller.GoFeatureFlagApiOptions{
184-
Endpoint: "http://localhost:1031",
185-
HTTPClient: client,
188+
Endpoint: "http://localhost:1031",
189+
HTTPClient: client,
190+
CustomHeaders: map[string]string{"User-Agent": "goff-sdk-tests"},
186191
}
187192
g := controller.NewGoFeatureFlagAPI(options)
188193
status, err := g.ConfigurationHasChanged()
189194
require.NoError(t, err)
190195
assert.Equal(t, controller.FlagConfigurationInitialized, status)
196+
assert.Equal(t, "goff-sdk-tests", mrt.GetLastRequest().Header.Get("User-Agent"))
191197
})
192198

193199
t.Run("Change in the configuration", func(t *testing.T) {

providers/go-feature-flag/pkg/provider.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ func NewProviderWithContext(ctx context.Context, options ProviderOptions) (*Prov
5151
ofrepOptions = append(ofrepOptions, ofrep.WithHeaderProvider(func() (key string, value string) {
5252
return controller.ContentTypeHeader, controller.ApplicationJson
5353
}))
54+
for k, v := range options.CustomHeaders {
55+
scopedK, scopedV := k, v
56+
ofrepOptions = append(ofrepOptions, ofrep.WithHeaderProvider(func() (key string, value string) {
57+
return scopedK, scopedV
58+
}))
59+
}
5460
ofrepProvider := ofrep.NewProvider(options.Endpoint, ofrepOptions...)
5561
cacheCtrl := controller.NewCache(options.FlagCacheSize, options.FlagCacheTTL, options.DisableCache)
5662

@@ -65,6 +71,7 @@ func NewProviderWithContext(ctx context.Context, options ProviderOptions) (*Prov
6571
Endpoint: options.Endpoint,
6672
HTTPClient: options.HTTPClient,
6773
APIKey: options.APIKey,
74+
CustomHeaders: options.CustomHeaders,
6875
ExporterMetadata: options.ExporterMetadata,
6976
})
7077
dataCollectorManager := controller.NewDataCollectorManager(

providers/go-feature-flag/pkg/provider_options.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ type ProviderOptions struct {
2424
// Default: null
2525
APIKey string
2626

27+
// CustomHeaders (optional) allows setting custom headers for every HTTP request.
28+
CustomHeaders map[string]string
29+
2730
// DisableCache (optional) set to true if you would like that every flag evaluation goes to the GO Feature Flag directly.
2831
DisableCache bool
2932

providers/go-feature-flag/pkg/provider_test.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,11 @@ type mockClient struct {
4040
flagChangeCallCount int
4141
collectorRequests []string
4242
requestBodies []string
43+
lastRequestHeader http.Header
4344
}
4445

4546
func (m *mockClient) roundTripFunc(req *http.Request) *http.Response {
47+
m.lastRequestHeader = req.Header.Clone()
4648
//read req body and store it
4749
var bodyBytes []byte
4850
if req.Body != nil {
@@ -323,9 +325,10 @@ func TestProvider_BooleanEvaluation(t *testing.T) {
323325
cli := mockClient{}
324326
t.Run(tt.name, func(t *testing.T) {
325327
options := gofeatureflag.ProviderOptions{
326-
Endpoint: "https://gofeatureflag.org/",
327-
HTTPClient: NewMockClient(cli.roundTripFunc),
328-
DisableCache: true,
328+
Endpoint: "https://gofeatureflag.org/",
329+
HTTPClient: NewMockClient(cli.roundTripFunc),
330+
CustomHeaders: map[string]string{"User-Agent": "goff-sdk-tests"},
331+
DisableCache: true,
329332
}
330333
provider, err := gofeatureflag.NewProvider(options)
331334
assert.NoError(t, err)
@@ -343,6 +346,9 @@ func TestProvider_BooleanEvaluation(t *testing.T) {
343346
assert.NoError(t, err)
344347
}
345348
assert.Equal(t, tt.want, value)
349+
if cli.callCount > 0 {
350+
assert.Equal(t, "goff-sdk-tests", cli.lastRequestHeader.Get("User-Agent"))
351+
}
346352
})
347353
}
348354
}

0 commit comments

Comments
 (0)