Skip to content

Commit dbe2851

Browse files
authored
fix: make client resilient to non-conforming responses from unleash-edge (#162)
* added unit test to verify the issue is fixed and to prevent regressions. Context: while the unleash server provides always valid responses, (at least some versions of) unleash-edge can provide an unexpected JSON reponse (null instead of empty array). This commit fixes the handling of the response, so we do not throw exceptions in this situation.
1 parent 85d430d commit dbe2851

File tree

2 files changed

+58
-2
lines changed

2 files changed

+58
-2
lines changed

lib/unleash/feature_toggle.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ def ensure_valid_context(context)
189189
end
190190

191191
def initialize_strategies(params, segment_map)
192-
params.fetch('strategies', [])
192+
(params.fetch('strategies', []) || [])
193193
.select{ |s| s.has_key?('name') && Unleash.strategies.includes?(s['name']) }
194194
.map do |s|
195195
ActivationStrategy.new(
@@ -202,7 +202,7 @@ def initialize_strategies(params, segment_map)
202202
end
203203

204204
def resolve_variants(strategy)
205-
strategy.fetch("variants", [])
205+
(strategy.fetch("variants", []) || [])
206206
.select{ |variant| variant.is_a?(Hash) && variant.has_key?("name") }
207207
.map do |variant|
208208
VariantDefinition.new(

spec/unleash/client_spec.rb

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,62 @@
297297
expect(WebMock).not_to have_requested(:post, 'http://test-url/client/metrics')
298298
end
299299

300+
it "should not fail if we are provided no variants from the unleash server" do
301+
WebMock.stub_request(:post, "http://test-url/client/register")
302+
.with(
303+
headers: {
304+
'Accept' => '*/*',
305+
'Content-Type' => 'application/json',
306+
'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
307+
'User-Agent' => 'Ruby',
308+
'X-Api-Key' => '123'
309+
}
310+
)
311+
.to_return(status: 200, body: "", headers: {})
312+
313+
features_response_body = '{
314+
"version": 1,
315+
"features": [{
316+
"name": "toggleName",
317+
"enabled": true,
318+
"strategies": [{ "name": "default", "constraints": [], "parameters": {}, "variants": null }],
319+
"variants": []
320+
}]
321+
}'
322+
323+
WebMock.stub_request(:get, "http://test-url/client/features")
324+
.with(
325+
headers: {
326+
'Accept' => '*/*',
327+
'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
328+
'Content-Type' => 'application/json',
329+
'Unleash-Appname' => 'my-test-app',
330+
'Unleash-Instanceid' => 'rspec/test',
331+
'User-Agent' => 'Ruby',
332+
'X-Api-Key' => '123'
333+
}
334+
)
335+
.to_return(status: 200, body: features_response_body, headers: {})
336+
337+
Unleash.configure do |config|
338+
config.url = 'http://test-url/'
339+
config.app_name = 'my-test-app'
340+
config.instance_id = 'rspec/test'
341+
config.disable_client = false
342+
config.disable_metrics = true
343+
config.custom_http_headers = { 'X-API-KEY' => '123' }
344+
end
345+
346+
unleash_client = Unleash::Client.new
347+
348+
expect(unleash_client.is_enabled?('toggleName', {})).to be true
349+
350+
expect(WebMock).not_to have_requested(:get, 'http://test-url/')
351+
expect(WebMock).to have_requested(:get, 'http://test-url/client/features')
352+
expect(WebMock).to have_requested(:post, 'http://test-url/client/register')
353+
expect(WebMock).not_to have_requested(:post, 'http://test-url/client/metrics')
354+
end
355+
300356
it "should forcefully disable metrics if the client is disabled" do
301357
Unleash.configure do |config|
302358
config.url = 'http://test-url/'

0 commit comments

Comments
 (0)