Skip to content

Commit 2e27b65

Browse files
committed
feat: throw-panic-with-multiple-custom-clients-and-conflicting-options
1 parent 1d5dda4 commit 2e27b65

File tree

4 files changed

+66
-23
lines changed

4 files changed

+66
-23
lines changed

client.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,14 @@ func NewClient(apiKey string, options ...Option) *Client {
7171
config: defaultConfig(),
7272
}
7373

74+
customClientCount := 0
7475
for _, opt := range options {
7576
name := getOptionQualifiedName(opt)
7677
if isClientOption(name) {
78+
customClientCount = customClientCount + 1
79+
if customClientCount > 1 {
80+
panic("Only one client option can be provided")
81+
}
7782
opt(c)
7883
}
7984
}
@@ -82,9 +87,13 @@ func NewClient(apiKey string, options ...Option) *Client {
8287
if c.client == nil {
8388
if c.httpClient != nil {
8489
c.client = resty.NewWithClient(c.httpClient)
90+
c.config.userProvidedClient = true
91+
8592
} else {
8693
c.client = resty.New()
8794
}
95+
} else {
96+
c.config.userProvidedClient = true
8897
}
8998

9099
c.client.SetHeaders(map[string]string{

client_test.go

Lines changed: 43 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,36 +1098,20 @@ func TestCustomRestyClientIsUsed(t *testing.T) {
10981098
assert.True(t, hasCustomHeader, "Expected custom resty header")
10991099
}
11001100

1101-
func TestRestyClientOverridesHTTPClient(t *testing.T) {
1102-
ctx := context.Background()
1103-
1104-
var customHeader string
1105-
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
1106-
customHeader = req.Header.Get("X-Test-Client")
1107-
rw.Header().Set("Content-Type", "application/json")
1108-
rw.WriteHeader(http.StatusOK)
1109-
_, err := io.WriteString(rw, fixtures.FlagsJson)
1110-
assert.NoError(t, err)
1111-
}))
1112-
defer server.Close()
1113-
1101+
func TestRestyClientOverridesHTTPClientShouldPanic(t *testing.T) {
11141102
httpClient := &http.Client{
11151103
Transport: roundTripperWithHeader("X-Test-Client", "http"),
11161104
}
11171105

11181106
restyClient := resty.New().
11191107
SetHeader("X-Test-Client", "resty")
11201108

1121-
client := flagsmith.NewClient(fixtures.EnvironmentAPIKey,
1122-
flagsmith.WithHTTPClient(httpClient),
1123-
flagsmith.WithRestyClient(restyClient),
1124-
flagsmith.WithBaseURL(server.URL+"/api/v1/"))
1125-
1126-
flags, err := client.GetFlags(ctx, nil)
1127-
1128-
assert.NoError(t, err)
1129-
assert.Equal(t, 1, len(flags.AllFlags()))
1130-
assert.Equal(t, "resty", customHeader, "Expected resty header")
1109+
assert.Panics(t, func() {
1110+
_ = flagsmith.NewClient(fixtures.EnvironmentAPIKey,
1111+
flagsmith.WithHTTPClient(httpClient),
1112+
flagsmith.WithRestyClient(restyClient),
1113+
flagsmith.WithBaseURL("http://example.com/api/v1/"))
1114+
}, "Expected panic when both HTTP and Resty clients are provided")
11311115
}
11321116

11331117
func TestDefaultRestyClientIsUsed(t *testing.T) {
@@ -1157,3 +1141,39 @@ func TestDefaultRestyClientIsUsed(t *testing.T) {
11571141
assert.True(t, serverCalled, "Expected server to be")
11581142
assert.Equal(t, 1, len(flags.AllFlags()))
11591143
}
1144+
1145+
func TestCustomClientOptionsShoudPanic(t *testing.T) {
1146+
restyClient := resty.New()
1147+
1148+
testCases := []struct {
1149+
name string
1150+
option flagsmith.Option
1151+
}{
1152+
{
1153+
name: "WithRequestTimeout",
1154+
option: flagsmith.WithRequestTimeout(5 * time.Second),
1155+
},
1156+
{
1157+
name: "WithRetries",
1158+
option: flagsmith.WithRetries(3, time.Second),
1159+
},
1160+
{
1161+
name: "WithCustomHeaders",
1162+
option: flagsmith.WithCustomHeaders(map[string]string{"X-Custom": "value"}),
1163+
},
1164+
{
1165+
name: "WithProxy",
1166+
option: flagsmith.WithProxy("http://proxy.example.com"),
1167+
},
1168+
}
1169+
1170+
for _, test := range testCases {
1171+
t.Run(test.name, func(t *testing.T) {
1172+
assert.Panics(t, func() {
1173+
_ = flagsmith.NewClient(fixtures.EnvironmentAPIKey,
1174+
flagsmith.WithRestyClient(restyClient),
1175+
test.option)
1176+
}, "Expected panic when using %s with custom resty client", test.name)
1177+
})
1178+
}
1179+
}

config.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ type config struct {
2727
realtimeBaseUrl string
2828
useRealtime bool
2929
polling bool
30+
userProvidedClient bool
3031
}
3132

3233
// defaultConfig returns default configuration.
@@ -36,5 +37,6 @@ func defaultConfig() config {
3637
timeout: DefaultTimeout,
3738
envRefreshInterval: time.Second * 60,
3839
realtimeBaseUrl: DefaultRealtimeBaseUrl,
40+
userProvidedClient: false,
3941
}
4042
}

options.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ func WithRemoteEvaluation() Option {
6565

6666
func WithRequestTimeout(timeout time.Duration) Option {
6767
return func(c *Client) {
68+
if c.config.userProvidedClient {
69+
panic("options modifying the client can not be used with a custom client")
70+
}
6871
c.client.SetTimeout(timeout)
6972
}
7073
}
@@ -89,13 +92,19 @@ func WithAnalytics(ctx context.Context) Option {
8992

9093
func WithRetries(count int, waitTime time.Duration) Option {
9194
return func(c *Client) {
95+
if c.config.userProvidedClient {
96+
panic("options modifying the client can not be used with a custom client")
97+
}
9298
c.client.SetRetryCount(count)
9399
c.client.SetRetryWaitTime(waitTime)
94100
}
95101
}
96102

97103
func WithCustomHeaders(headers map[string]string) Option {
98104
return func(c *Client) {
105+
if c.config.userProvidedClient {
106+
panic("options modifying the client can not be used with a custom client")
107+
}
99108
c.client.SetHeaders(headers)
100109
}
101110
}
@@ -124,6 +133,9 @@ func WithSlogLogger(logger *slog.Logger) Option {
124133
// The proxyURL argument is a string representing the URL of the proxy server to use, e.g. "http://proxy.example.com:8080".
125134
func WithProxy(proxyURL string) Option {
126135
return func(c *Client) {
136+
if c.config.userProvidedClient {
137+
panic("options modifying the client can not be used with a custom client")
138+
}
127139
c.client.SetProxy(proxyURL)
128140
}
129141
}

0 commit comments

Comments
 (0)