diff --git a/lib/puppet/file_serving/http_metadata.rb b/lib/puppet/file_serving/http_metadata.rb index d5c287c337..f50bdd406e 100644 --- a/lib/puppet/file_serving/http_metadata.rb +++ b/lib/puppet/file_serving/http_metadata.rb @@ -13,8 +13,6 @@ def initialize(http_response, path = '/dev/null') # hash available checksums for eventual collection @checksums = {} - # use a default mtime in case there is no usable HTTP header - @checksums[:mtime] = "{mtime}#{Time.now}" # RFC-1864, deprecated in HTTP/1.1 due to partial responses checksum = http_response['content-md5'] @@ -82,5 +80,8 @@ def collect @checksum = @checksums[type] break if @checksum end + + # If no checksum was found in headers, leave checksum as nil + # The HTTP indirector will need to fetch content to compute a checksum end end diff --git a/lib/puppet/indirector/file_metadata/http.rb b/lib/puppet/indirector/file_metadata/http.rb index b50fd6fa59..cf06a03d39 100644 --- a/lib/puppet/indirector/file_metadata/http.rb +++ b/lib/puppet/indirector/file_metadata/http.rb @@ -17,17 +17,21 @@ def find(request) client = Puppet.runtime[:http] head = client.head(uri, options: { include_system_store: true }) - return create_httpmetadata(head, checksum_type) if head.success? + metadata = create_httpmetadata(head, checksum_type) + return metadata if metadata.checksum - case head.code - when 403, 405 - # AMZ presigned URL and puppetserver may return 403 - # instead of 405. Fallback to partial get - get = partial_get(client, uri) - return create_httpmetadata(get, checksum_type) if get.success? - end + # If no checksum headers were available, fetch the content to compute a checksum + get = client.get(uri, options: { include_system_store: true }) + return nil unless get.success? - nil + # Compute checksum from the content + content = get.body + checksum_type ||= Puppet[:digest_algorithm].to_sym + checksum = "{#{checksum_type}}" + Digest.const_get(checksum_type.to_s.upcase).hexdigest(content) + + metadata.checksum = checksum + metadata.checksum_type = checksum_type + metadata end def search(request) diff --git a/spec/unit/indirector/file_metadata/http_spec.rb b/spec/unit/indirector/file_metadata/http_spec.rb index 12f17ee913..15e8099c8d 100644 --- a/spec/unit/indirector/file_metadata/http_spec.rb +++ b/spec/unit/indirector/file_metadata/http_spec.rb @@ -29,16 +29,18 @@ end context "when finding" do - it "returns http file metadata" do + it "returns http file metadata and fetches content to compute checksum when no headers available" do stub_request(:head, key) .to_return(status: 200, headers: DEFAULT_HEADERS) + stub_request(:get, key) + .to_return(status: 200, body: "test content") result = model.indirection.find(key) expect(result.ftype).to eq('file') expect(result.path).to eq('/dev/null') expect(result.relative_path).to be_nil expect(result.destination).to be_nil - expect(result.checksum).to match(%r{mtime}) + expect(result.checksum).to match(%r{sha256}) expect(result.owner).to be_nil expect(result.group).to be_nil expect(result.mode).to be_nil