Skip to content

Commit 91c3726

Browse files
committed
Merge pull request #9272 from gtirloni/9271-http416
Fix gzip cache corruption when recovering from HTTP 416 responses (cherry picked from commit 999afe3)
1 parent 5cb0563 commit 91c3726

2 files changed

Lines changed: 32 additions & 1 deletion

File tree

bundler/lib/bundler/fetcher/downloader.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ def fetch(uri, headers = {}, counter = 0)
5454
when Gem::Net::HTTPRequestedRangeNotSatisfiable
5555
new_headers = headers.dup
5656
new_headers.delete("Range")
57-
new_headers["Accept-Encoding"] = "gzip"
5857
fetch(uri, new_headers)
5958
when Gem::Net::HTTPRequestEntityTooLarge
6059
raise FallbackError, response.body

bundler/spec/bundler/fetcher/downloader_spec.rb

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,38 @@
126126
end
127127
end
128128

129+
context "when the request response is a Gem::Net::HTTPRequestedRangeNotSatisfiable" do
130+
let(:http_response) { Gem::Net::HTTPRequestedRangeNotSatisfiable.new("1.1", 416, "Range Not Satisfiable") }
131+
let(:success_response) { Gem::Net::HTTPSuccess.new("1.1", 200, "Success") }
132+
let(:options) { { "Range" => "bytes=1000-", "If-None-Match" => "some-etag" } }
133+
134+
before do
135+
# First request returns 416, retry request returns success
136+
allow(subject).to receive(:request).with(uri, options).and_return(http_response)
137+
allow(subject).to receive(:request).with(uri, { "If-None-Match" => "some-etag" }).and_return(success_response)
138+
end
139+
140+
# The 416 handler removes the Range header and retries without incrementing the counter.
141+
# Importantly, it does NOT add Accept-Encoding header, which would break Ruby's
142+
# automatic gzip decompression (see issue #9271 for details on that bug).
143+
it "should retry the request without the Range header" do
144+
expect(subject).to receive(:request).with(uri, options).ordered
145+
expect(subject).to receive(:request).with(uri, hash_excluding("Range", "Accept-Encoding")).ordered
146+
subject.fetch(uri, options, counter)
147+
end
148+
149+
it "should preserve other headers on retry" do
150+
expect(subject).to receive(:request).with(uri, options).ordered
151+
expect(subject).to receive(:request).with(uri, hash_including("If-None-Match" => "some-etag")).ordered
152+
subject.fetch(uri, options, counter)
153+
end
154+
155+
it "should return the successful response" do
156+
result = subject.fetch(uri, options, counter)
157+
expect(result).to eq(success_response)
158+
end
159+
end
160+
129161
context "when the request response is some other type" do
130162
let(:http_response) { Gem::Net::HTTPBadGateway.new("1.1", 500, "Fatal Error") }
131163

0 commit comments

Comments
 (0)