Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions providers/go-feature-flag/pkg/controller/goff_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ type GoFeatureFlagApiOptions struct {
// (This feature is available only if you are using GO Feature Flag relay proxy v1.7.0 or above)
// Default: null
APIKey string
// CustomHeaders (optional) allows setting custom headers for every HTTP request.
// Default: null
CustomHeaders map[string]string
// ExporterMetadata (optional) If we set metadata, it will be sent with every data collection requests along with the events.
ExporterMetadata map[string]any
}
Expand Down Expand Up @@ -61,6 +64,9 @@ func (g *GoFeatureFlagAPI) CollectData(events []model.FeatureEvent) error {
if g.options.APIKey != "" {
req.Header.Set(AuthorizationHeader, BearerPrefix+g.options.APIKey)
}
for k, v := range g.options.CustomHeaders {
req.Header.Set(k, v)
}

response, err := g.getHttpClient().Do(req)
if err != nil {
Expand All @@ -87,6 +93,9 @@ func (g *GoFeatureFlagAPI) ConfigurationHasChanged() (ConfigurationChangeStatus,
if g.options.APIKey != "" {
req.Header.Set(AuthorizationHeader, BearerPrefix+g.options.APIKey)
}
for k, v := range g.options.CustomHeaders {
req.Header.Set(k, v)
}
if g.configChangeEtag != "" {
req.Header.Set(IfNoneMatchHeader, g.configChangeEtag)
}
Expand Down
10 changes: 8 additions & 2 deletions providers/go-feature-flag/pkg/controller/goff_api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ func Test_CollectDataAPI(t *testing.T) {
options: controller.GoFeatureFlagApiOptions{
Endpoint: "http://localhost:1031",
APIKey: "",
CustomHeaders: map[string]string{"User-Agent": "goff-sdk-tests"},
ExporterMetadata: map[string]any{"openfeature": true, "provider": "go"},
},
events: []model.FeatureEvent{
Expand Down Expand Up @@ -67,6 +68,7 @@ func Test_CollectDataAPI(t *testing.T) {
wantHeaders: func() http.Header {
headers := http.Header{}
headers.Set(controller.ContentTypeHeader, controller.ApplicationJson)
headers.Set("User-Agent", "goff-sdk-tests")
return headers
}(),
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\"}}",
Expand All @@ -77,6 +79,7 @@ func Test_CollectDataAPI(t *testing.T) {
options: controller.GoFeatureFlagApiOptions{
Endpoint: "http://localhost:1031",
APIKey: "my-key",
CustomHeaders: map[string]string{"User-Agent": "goff-sdk-tests"},
ExporterMetadata: map[string]any{"openfeature": true, "provider": "go"},
},
events: []model.FeatureEvent{
Expand Down Expand Up @@ -115,6 +118,7 @@ func Test_CollectDataAPI(t *testing.T) {
headers := http.Header{}
headers.Set(controller.ContentTypeHeader, controller.ApplicationJson)
headers.Set(controller.AuthorizationHeader, controller.BearerPrefix+"my-key")
headers.Set("User-Agent", "goff-sdk-tests")
return headers
}(),
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\"}}",
Expand Down Expand Up @@ -181,13 +185,15 @@ func Test_ConfigurationHasChanged(t *testing.T) {
}}
client := &http.Client{Transport: &mrt}
options := controller.GoFeatureFlagApiOptions{
Endpoint: "http://localhost:1031",
HTTPClient: client,
Endpoint: "http://localhost:1031",
HTTPClient: client,
CustomHeaders: map[string]string{"User-Agent": "goff-sdk-tests"},
}
g := controller.NewGoFeatureFlagAPI(options)
status, err := g.ConfigurationHasChanged()
require.NoError(t, err)
assert.Equal(t, controller.FlagConfigurationInitialized, status)
assert.Equal(t, "goff-sdk-tests", mrt.GetLastRequest().Header.Get("User-Agent"))
})

t.Run("Change in the configuration", func(t *testing.T) {
Expand Down
7 changes: 7 additions & 0 deletions providers/go-feature-flag/pkg/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ func NewProviderWithContext(ctx context.Context, options ProviderOptions) (*Prov
ofrepOptions = append(ofrepOptions, ofrep.WithHeaderProvider(func() (key string, value string) {
return controller.ContentTypeHeader, controller.ApplicationJson
}))
for k, v := range options.CustomHeaders {
scopedK, scopedV := k, v
ofrepOptions = append(ofrepOptions, ofrep.WithHeaderProvider(func() (key string, value string) {
return scopedK, scopedV
}))
}
ofrepProvider := ofrep.NewProvider(options.Endpoint, ofrepOptions...)
cacheCtrl := controller.NewCache(options.FlagCacheSize, options.FlagCacheTTL, options.DisableCache)

Expand All @@ -65,6 +71,7 @@ func NewProviderWithContext(ctx context.Context, options ProviderOptions) (*Prov
Endpoint: options.Endpoint,
HTTPClient: options.HTTPClient,
APIKey: options.APIKey,
CustomHeaders: options.CustomHeaders,
ExporterMetadata: options.ExporterMetadata,
})
dataCollectorManager := controller.NewDataCollectorManager(
Expand Down
3 changes: 3 additions & 0 deletions providers/go-feature-flag/pkg/provider_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ type ProviderOptions struct {
// Default: null
APIKey string

// CustomHeaders (optional) allows setting custom headers for every HTTP request.
CustomHeaders map[string]string

// DisableCache (optional) set to true if you would like that every flag evaluation goes to the GO Feature Flag directly.
DisableCache bool

Expand Down
12 changes: 9 additions & 3 deletions providers/go-feature-flag/pkg/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,11 @@ type mockClient struct {
flagChangeCallCount int
collectorRequests []string
requestBodies []string
lastRequestHeader http.Header
}

func (m *mockClient) roundTripFunc(req *http.Request) *http.Response {
m.lastRequestHeader = req.Header.Clone()
//read req body and store it
var bodyBytes []byte
if req.Body != nil {
Expand Down Expand Up @@ -323,9 +325,10 @@ func TestProvider_BooleanEvaluation(t *testing.T) {
cli := mockClient{}
t.Run(tt.name, func(t *testing.T) {
options := gofeatureflag.ProviderOptions{
Endpoint: "https://gofeatureflag.org/",
HTTPClient: NewMockClient(cli.roundTripFunc),
DisableCache: true,
Endpoint: "https://gofeatureflag.org/",
HTTPClient: NewMockClient(cli.roundTripFunc),
CustomHeaders: map[string]string{"User-Agent": "goff-sdk-tests"},
DisableCache: true,
}
provider, err := gofeatureflag.NewProvider(options)
assert.NoError(t, err)
Expand All @@ -343,6 +346,9 @@ func TestProvider_BooleanEvaluation(t *testing.T) {
assert.NoError(t, err)
}
assert.Equal(t, tt.want, value)
if cli.callCount > 0 {
assert.Equal(t, "goff-sdk-tests", cli.lastRequestHeader.Get("User-Agent"))
}
})
}
}
Expand Down
Loading