Skip to content

Commit ced5fb3

Browse files
committed
Treat non-redirect 304 responses as API status errors
1 parent 761dffa commit ced5fb3

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}] .
@@ -383,7 +393,8 @@ def send_request(request, redirect_count:, retry_count:, send_retry_header:)
383393
case status
384394
in ..299
385395
[status, response, stream]
386-
in 300..399 if redirect_count >= self.class::MAX_REDIRECTS
396+
in Integer => status if self.class.redirect_status?(status) &&
397+
redirect_count >= self.class::MAX_REDIRECTS
387398
self.class.reap_connection!(status, stream: stream)
388399

389400
message = "Failed to complete the request within #{self.class::MAX_REDIRECTS} redirects."
@@ -392,7 +403,7 @@ def send_request(request, redirect_count:, retry_count:, send_retry_header:)
392403
response: response,
393404
message: message
394405
)
395-
in 300..399
406+
in Integer => status if self.class.redirect_status?(status)
396407
self.class.reap_connection!(status, stream: stream)
397408

398409
request = self.class.follow_redirect(request, status: status, response_headers: headers)
@@ -404,7 +415,7 @@ def send_request(request, redirect_count:, retry_count:, send_retry_header:)
404415
)
405416
in DockerEngineRuby::Errors::APIConnectionError if retry_count >= max_retries
406417
raise status
407-
in (400..) if retry_count >= max_retries || !self.class.should_retry?(status, headers: headers)
418+
in (300..) if retry_count >= max_retries || !self.class.should_retry?(status, headers: headers)
408419
decoded = Kernel.then do
409420
DockerEngineRuby::Internal::Util.decode_content(headers, stream: stream, suppress_error: true)
410421
ensure

test/docker_engine_ruby/client_test.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,18 @@ def test_client_redirect_auth_strip_cross_origin
282282
end
283283
end
284284

285+
def test_non_redirect_304_is_treated_as_status_error
286+
stub_request(:post, "http://localhost/containers/id/start").to_return(status: 304, body: "")
287+
288+
docker = DockerEngineRuby::Client.new(base_url: "http://localhost")
289+
290+
error = assert_raises(DockerEngineRuby::Errors::APIStatusError) do
291+
docker.containers.start("id")
292+
end
293+
294+
assert_equal(304, error.status)
295+
end
296+
285297
def test_default_headers
286298
stub_request(:get, "http://localhost/containers/json").to_return_json(status: 200, body: {})
287299

0 commit comments

Comments
 (0)