Skip to content

Commit eaee7e6

Browse files
committed
Treat non-redirect 304 responses as API status errors
1 parent 9f71099 commit eaee7e6

File tree

2 files changed

+26
-3
lines changed

2 files changed

+26
-3
lines changed

lib/docker_engine_ruby/internal/transport/base_client.rb

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ class BaseClient
1111

1212
# from whatwg fetch spec
1313
MAX_REDIRECTS = 20
14+
REDIRECT_STATUSES = [301, 302, 303, 307, 308].freeze
1415

1516
# rubocop:disable Style/MutableConstant
1617
PLATFORM_HEADERS =
@@ -67,6 +68,15 @@ def should_retry?(status, headers:)
6768
end
6869
end
6970

71+
# @api private
72+
#
73+
# @param status [Integer]
74+
#
75+
# @return [Boolean]
76+
def redirect_status?(status)
77+
REDIRECT_STATUSES.include?(status)
78+
end
79+
7080
# @api private
7181
#
7282
# @param request [Hash{Symbol=>Object}] .
@@ -393,7 +403,8 @@ def send_request(request, redirect_count:, retry_count:, send_retry_header:)
393403
case status
394404
in ..299
395405
[status, response, stream]
396-
in 300..399 if redirect_count >= self.class::MAX_REDIRECTS
406+
in Integer => status if self.class.redirect_status?(status) &&
407+
redirect_count >= self.class::MAX_REDIRECTS
397408
self.class.reap_connection!(status, stream: stream)
398409

399410
message = "Failed to complete the request within #{self.class::MAX_REDIRECTS} redirects."
@@ -402,7 +413,7 @@ def send_request(request, redirect_count:, retry_count:, send_retry_header:)
402413
response: response,
403414
message: message
404415
)
405-
in 300..399
416+
in Integer => status if self.class.redirect_status?(status)
406417
self.class.reap_connection!(status, stream: stream)
407418

408419
request = self.class.follow_redirect(request, status: status, response_headers: headers)
@@ -414,7 +425,7 @@ def send_request(request, redirect_count:, retry_count:, send_retry_header:)
414425
)
415426
in DockerEngineRuby::Errors::APIConnectionError if retry_count >= max_retries
416427
raise status
417-
in (400..) if retry_count >= max_retries || !self.class.should_retry?(status, headers: headers)
428+
in (300..) if retry_count >= max_retries || !self.class.should_retry?(status, headers: headers)
418429
decoded = Kernel.then do
419430
DockerEngineRuby::Internal::Util.decode_content(headers, stream: stream, suppress_error: true)
420431
ensure

test/docker_engine_ruby/client_test.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,18 @@ def test_images_pull_with_json_lines_response_returns_nil
342342
assert_nil(response)
343343
end
344344

345+
def test_non_redirect_304_is_treated_as_status_error
346+
stub_request(:post, "http://localhost/containers/id/start").to_return(status: 304, body: "")
347+
348+
docker = DockerEngineRuby::Client.new(base_url: "http://localhost")
349+
350+
error = assert_raises(DockerEngineRuby::Errors::APIStatusError) do
351+
docker.containers.start("id")
352+
end
353+
354+
assert_equal(304, error.status)
355+
end
356+
345357
def test_default_headers
346358
stub_request(:get, "http://localhost/containers/json").to_return_json(status: 200, body: {})
347359

0 commit comments

Comments
 (0)