Skip to content

Commit f81f506

Browse files
thomaspoignantc4milo
authored andcommitted
feat: Support apiKey for GO Feature Flag relay proxy v1.7.0 (open-feature#166)
Signed-off-by: Thomas Poignant <[email protected]>
1 parent 1b4302a commit f81f506

File tree

3 files changed

+61
-0
lines changed

3 files changed

+61
-0
lines changed

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

+26
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ type Provider struct {
2121
httpClient HTTPClient
2222
endpoint string
2323
goFeatureFlagInstance *client.GoFeatureFlag
24+
apiKey string
2425
}
2526

2627
// HTTPClient is a custom interface to be able to override it by any implementation
@@ -64,6 +65,7 @@ func NewProvider(options ProviderOptions) (*Provider, error) {
6465
}
6566

6667
return &Provider{
68+
apiKey: options.APIKey,
6769
endpoint: options.Endpoint,
6870
httpClient: httpClient,
6971
}, nil
@@ -276,6 +278,9 @@ func evaluateWithRelayProxy[T model.JsonType](provider *Provider, ctx context.Co
276278
}
277279
}
278280
goffRequest.Header.Set("Content-Type", "application/json")
281+
if provider.apiKey != "" {
282+
goffRequest.Header.Set("Authorization", fmt.Sprintf("Bearer %s", provider.apiKey))
283+
}
279284

280285
response, err := provider.httpClient.Do(goffRequest)
281286
if err != nil {
@@ -298,6 +303,27 @@ func evaluateWithRelayProxy[T model.JsonType](provider *Provider, ctx context.Co
298303
}
299304
}
300305

306+
if response.StatusCode == http.StatusUnauthorized {
307+
return model.GenericResolutionDetail[T]{
308+
Value: defaultValue,
309+
ProviderResolutionDetail: of.ProviderResolutionDetail{
310+
ResolutionError: of.NewGeneralResolutionError(
311+
"invalid token used to contact GO Feature Flag relay proxy instance"),
312+
Reason: of.ErrorReason,
313+
},
314+
}
315+
}
316+
if response.StatusCode >= http.StatusBadRequest {
317+
return model.GenericResolutionDetail[T]{
318+
Value: defaultValue,
319+
ProviderResolutionDetail: of.ProviderResolutionDetail{
320+
ResolutionError: of.NewGeneralResolutionError(
321+
"unexpected answer from the relay proxy"),
322+
Reason: of.ErrorReason,
323+
},
324+
}
325+
}
326+
301327
var evalResponse model.EvalResponse[T]
302328
err = json.Unmarshal(responseStr, &evalResponse)
303329
if err != nil {

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

+6
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,10 @@ type ProviderOptions struct {
1616
// GOFeatureFlagConfig is the configuration struct for the GO Feature Flag module.
1717
// If not nil we will launch the provider using the GO Feature Flag module.
1818
GOFeatureFlagConfig *ffclient.Config
19+
20+
// APIKey (optional) If the relay proxy is configured to authenticate the requests, you should provide
21+
// an API Key to the provider. Please ask the administrator of the relay proxy to provide an API Key.
22+
// (This feature is available only if you are using GO Feature Flag relay proxy v1.7.0 or above)
23+
// Default: null
24+
APIKey string
1925
}

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

+29
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ type mockClient struct{}
2020
func (m *mockClient) Do(req *http.Request) (*http.Response, error) {
2121
mockPath := "../testutils/mock_responses/%s.json"
2222
flagName := strings.Replace(strings.Replace(req.URL.Path, "/v1/feature/", "", -1), "/eval", "", -1)
23+
24+
if flagName == "unauthorized" {
25+
return &http.Response{
26+
StatusCode: http.StatusUnauthorized,
27+
Body: io.NopCloser(bytes.NewReader([]byte(""))),
28+
}, nil
29+
}
30+
2331
content, err := os.ReadFile(fmt.Sprintf(mockPath, flagName))
2432
if err != nil {
2533
content, _ = os.ReadFile(fmt.Sprintf(mockPath, "flag_not_found"))
@@ -65,6 +73,27 @@ func TestProvider_BooleanEvaluation(t *testing.T) {
6573
args args
6674
want of.BooleanEvaluationDetails
6775
}{
76+
{
77+
name: "unauthorized flag",
78+
args: args{
79+
flag: "unauthorized",
80+
defaultValue: false,
81+
evalCtx: defaultEvaluationCtx(),
82+
},
83+
want: of.BooleanEvaluationDetails{
84+
Value: false,
85+
EvaluationDetails: of.EvaluationDetails{
86+
FlagKey: "unauthorized",
87+
FlagType: of.Boolean,
88+
ResolutionDetail: of.ResolutionDetail{
89+
Variant: "",
90+
Reason: of.ErrorReason,
91+
ErrorCode: of.GeneralCode,
92+
ErrorMessage: "invalid token used to contact GO Feature Flag relay proxy instance",
93+
},
94+
},
95+
},
96+
},
6897
{
6998
name: "should resolve a valid boolean flag with TARGETING_MATCH reason",
7099
args: args{

0 commit comments

Comments
 (0)