Skip to content

Commit a3caeff

Browse files
committed
Handle Encoded Downloads
Previously, all downloads passed through DownloadCache required that the value of the Content-Length header matched the size of the file that was actually downloaded. This did not take into account compressed encoding schemes for the artifacts and would fail when they were compressed. This change detects when an artifact is compressed and skips the size validation. [#116036875]
1 parent 0cfa3df commit a3caeff

File tree

2 files changed

+20
-2
lines changed

2 files changed

+20
-2
lines changed

lib/java_buildpack/util/cache/download_cache.rb

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ def attempt(http, request, cached_file)
144144
end
145145

146146
def cache_content(response, cached_file)
147+
compressed = compressed?(response)
148+
147149
cached_file.cached(File::CREAT | File::WRONLY | File::BINARY) do |f|
148150
@logger.debug { "Persisting content to #{f.path}" }
149151

@@ -152,7 +154,7 @@ def cache_content(response, cached_file)
152154
f.fsync
153155
end
154156

155-
validate_size response['Content-Length'], cached_file
157+
validate_size response['Content-Length'], cached_file unless compressed
156158
end
157159

158160
def cache_etag(response, cached_file)
@@ -183,6 +185,10 @@ def cache_last_modified(response, cached_file)
183185
end
184186
end
185187

188+
def compressed?(response)
189+
%w(br compress deflate gzip x-gzip).include?(response['Content-Encoding'])
190+
end
191+
186192
def debug_ssl(http)
187193
socket = http.instance_variable_get('@socket')
188194
return unless socket
@@ -300,7 +306,7 @@ def validate_size(expected_size, cached_file)
300306
actual_size = cached_file.cached(File::RDONLY) { |f| f.size }
301307
@logger.debug { "Validated content size #{actual_size} is #{expected_size}" }
302308

303-
return if expected_size.to_i == actual_size
309+
return if (expected_size.to_i == actual_size)
304310

305311
cached_file.destroy
306312
fail InferredNetworkFailure, "Content has invalid size. Was #{actual_size}, should be #{expected_size}."

spec/java_buildpack/util/cache/download_cache_spec.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,18 @@
170170
expect { |b| download_cache.get uri, &b }.to yield_file_with_content(/foo-cached/)
171171
end
172172

173+
it 'ignores incorrect size when encoded' do
174+
stub_request(:get, uri)
175+
.to_return(status: 200, body: 'foo-cac', headers: { Etag: 'foo-etag',
176+
'Content-Encoding' => 'gzip',
177+
'Last-Modified' => 'foo-last-modified',
178+
'Content-Length' => 10 })
179+
180+
touch immutable_cache_root, 'cached', 'old-foo-cached'
181+
182+
expect { |b| download_cache.get uri, &b }.to yield_file_with_content(/foo-cac/)
183+
end
184+
173185
context do
174186

175187
let(:environment) { { 'http_proxy' => 'http://proxy:9000', 'HTTP_PROXY' => nil } }

0 commit comments

Comments
 (0)