Skip to content

Commit 4e2488f

Browse files
committed
Version aware PATCH vs POST
1 parent d757102 commit 4e2488f

4 files changed

Lines changed: 178 additions & 4 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77
## [Unreleased]
88

99
### Changed
10-
- Use `PATCH` not `POST` when modifying proxies.
10+
- Use `PATCH` not `POST` when enabling or disabling proxies when Toxiproxy supports `PATCH`.
1111
([#186](https://github.com/Shopify/toxiproxy-ruby/pull/186), @brendo)
1212
- Set HTTP timeout of 5s when communicating with Toxiproxy server.
1313
([#85](https://github.com/Shopify/toxiproxy-ruby/pull/85), @casperisfine)

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
[![Gem Version](https://badge.fury.io/rb/toxiproxy.svg)](https://badge.fury.io/rb/toxiproxy)
44
[![Test](https://github.com/Shopify/toxiproxy-ruby/actions/workflows/test.yml/badge.svg)](https://github.com/Shopify/toxiproxy-ruby/actions/workflows/test.yml)
55

6-
- `toxiproxy-ruby` `>= 3.x` is compatible with the Toxiproxy `2.6+` series.
76
- `toxiproxy-ruby` `>= 1.x` is compatible with the Toxiproxy `2.x` series.
87
- `toxiproxy-ruby` `0.x` is compatible with the Toxiproxy `1.x` series.
98

lib/toxiproxy.rb

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,11 @@ def down(&block)
212212

213213
# Disables a Toxiproxy. This will drop all active connections and stop the proxy from listening.
214214
def disable
215-
request = Net::HTTP::Patch.new("/proxies/#{name}")
215+
request = if server_supports_patch?
216+
Net::HTTP::Patch.new("/proxies/#{name}")
217+
else
218+
Net::HTTP::Post.new("/proxies/#{name}")
219+
end
216220
request["Content-Type"] = "application/json"
217221

218222
hash = { enabled: false }
@@ -225,7 +229,11 @@ def disable
225229

226230
# Enables a Toxiproxy. This will cause the proxy to start listening again.
227231
def enable
228-
request = Net::HTTP::Patch.new("/proxies/#{name}")
232+
request = if server_supports_patch?
233+
Net::HTTP::Patch.new("/proxies/#{name}")
234+
else
235+
Net::HTTP::Post.new("/proxies/#{name}")
236+
end
229237
request["Content-Type"] = "application/json"
230238

231239
hash = { enabled: true }
@@ -283,6 +291,35 @@ def toxics
283291

284292
private
285293

294+
def version_string
295+
return @version_string if @version_string
296+
297+
version_response = self.class.version
298+
return false if version_response == false
299+
300+
@version_string = begin
301+
JSON.parse(version_response)["version"]
302+
rescue JSON::ParserError
303+
false
304+
end
305+
end
306+
307+
# Check if the toxiproxy server version supports PATCH for enable/disable
308+
def server_supports_patch?
309+
version_str = version_string
310+
return false if version_str == false
311+
312+
begin
313+
# Use Gem::Version for proper version comparison
314+
current_version = Gem::Version.new(version_str.sub(/^v/, "")) # Remove 'v' prefix if present
315+
required_version = Gem::Version.new("2.6.0")
316+
current_version >= required_version
317+
rescue ArgumentError
318+
# Invalid version format
319+
false
320+
end
321+
end
322+
286323
def http_request(request)
287324
self.class.http_request(request)
288325
end

test/toxiproxy_test.rb

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,144 @@ def test_version
387387
assert_instance_of(String, Toxiproxy.version)
388388
end
389389

390+
def test_server_supports_patch_with_version_2_6_0
391+
Toxiproxy.stub(:version, '{"version": "2.6.0"}') do
392+
assert(Toxiproxy.new(upstream: "localhost:3306", name: "test").send(:server_supports_patch?))
393+
end
394+
end
395+
396+
def test_server_supports_patch_with_version_2_7_0
397+
Toxiproxy.stub(:version, '{"version": "2.7.0"}') do
398+
assert(Toxiproxy.new(upstream: "localhost:3306", name: "test").send(:server_supports_patch?))
399+
end
400+
end
401+
402+
def test_server_supports_patch_with_version_3_0_0
403+
Toxiproxy.stub(:version, '{"version": "3.0.0"}') do
404+
assert(Toxiproxy.new(upstream: "localhost:3306", name: "test").send(:server_supports_patch?))
405+
end
406+
end
407+
408+
def test_does_not_support_patch_for_enable_disable_with_version_below_2_6_0
409+
Toxiproxy.stub(:version, '{"version": "2.5.0"}') do
410+
refute(Toxiproxy.new(upstream: "localhost:3306", name: "test").send(:server_supports_patch?))
411+
end
412+
end
413+
414+
def test_does_not_support_patch_for_enable_disable_when_not_running
415+
Toxiproxy.stub(:running?, false) do
416+
refute(Toxiproxy.new(upstream: "localhost:3306", name: "test").send(:server_supports_patch?))
417+
end
418+
end
419+
420+
def test_does_not_support_patch_for_enable_disable_with_invalid_version
421+
Toxiproxy.stub(:version, "invalid") do
422+
refute(Toxiproxy.new(upstream: "localhost:3306", name: "test").send(:server_supports_patch?))
423+
end
424+
end
425+
426+
def test_disable_uses_patch_when_version_supports_it
427+
proxy = Toxiproxy.new(upstream: "localhost:3306", name: "test_proxy_patch")
428+
429+
# Mock version to return JSON with 2.6.0 (supports PATCH)
430+
Toxiproxy.stub(:version, '{"version": "2.6.0"}') do
431+
# Mock the http_request method to capture the request type
432+
request_captured = nil
433+
proxy.stub(:http_request, ->(req) {
434+
request_captured = req
435+
double = Object.new
436+
double.define_singleton_method(:value) do
437+
nil
438+
end
439+
double
440+
}) do
441+
proxy.disable
442+
end
443+
444+
# Verify PATCH was used
445+
assert_instance_of(Net::HTTP::Patch, request_captured)
446+
assert_equal("/proxies/test_proxy_patch", request_captured.path)
447+
assert_equal({ enabled: false }.to_json, request_captured.body)
448+
end
449+
end
450+
451+
def test_enable_uses_patch_when_version_supports_it
452+
proxy = Toxiproxy.new(upstream: "localhost:3306", name: "test_proxy_patch_enable")
453+
454+
# Mock version to return JSON with 2.6.0 (supports PATCH)
455+
Toxiproxy.stub(:version, '{"version": "2.6.0"}') do
456+
# Mock the http_request method to capture the request type
457+
request_captured = nil
458+
proxy.stub(:http_request, ->(req) {
459+
request_captured = req
460+
double = Object.new
461+
double.define_singleton_method(:value) do
462+
nil
463+
end
464+
double
465+
}) do
466+
proxy.enable
467+
end
468+
469+
# Verify PATCH was used
470+
assert_instance_of(Net::HTTP::Patch, request_captured)
471+
assert_equal("/proxies/test_proxy_patch_enable", request_captured.path)
472+
assert_equal({ enabled: true }.to_json, request_captured.body)
473+
end
474+
end
475+
476+
def test_disable_uses_post_when_version_does_not_support_patch
477+
proxy = Toxiproxy.new(upstream: "localhost:3306", name: "test_proxy_post")
478+
479+
# Mock version to return JSON with 2.5.0 (does not support PATCH)
480+
481+
Toxiproxy.stub(:version, '{"version": "2.5.0"}') do
482+
# Mock the http_request method to capture the request type
483+
request_captured = nil
484+
proxy.stub(:http_request, ->(req) {
485+
request_captured = req
486+
double = Object.new
487+
double.define_singleton_method(:value) do
488+
nil
489+
end
490+
double
491+
}) do
492+
proxy.disable
493+
end
494+
495+
# Verify POST was used
496+
assert_instance_of(Net::HTTP::Post, request_captured)
497+
assert_equal("/proxies/test_proxy_post", request_captured.path)
498+
assert_equal({ enabled: false }.to_json, request_captured.body)
499+
end
500+
end
501+
502+
def test_enable_uses_post_when_version_does_not_support_patch
503+
proxy = Toxiproxy.new(upstream: "localhost:3306", name: "test_proxy_post_enable")
504+
505+
# Mock version to return JSON with 2.5.0 (does not support PATCH)
506+
507+
Toxiproxy.stub(:version, '{"version": "2.5.0"}') do
508+
# Mock the http_request method to capture the request type
509+
request_captured = nil
510+
proxy.stub(:http_request, ->(req) {
511+
request_captured = req
512+
double = Object.new
513+
double.define_singleton_method(:value) do
514+
nil
515+
end
516+
double
517+
}) do
518+
proxy.enable
519+
end
520+
521+
# Verify POST was used
522+
assert_instance_of(Net::HTTP::Post, request_captured)
523+
assert_equal("/proxies/test_proxy_post_enable", request_captured.path)
524+
assert_equal({ enabled: true }.to_json, request_captured.body)
525+
end
526+
end
527+
390528
def test_multiple_of_same_toxic_type
391529
with_tcpserver(receive: true) do |port|
392530
proxy = Toxiproxy.create(upstream: "localhost:#{port}", name: "test_proxy")

0 commit comments

Comments
 (0)