diff --git a/lib/api/files.rb b/lib/api/files.rb index f3de7fbe96b4b5e9432689d6f3c7ffd9be4fb9ef..9d2b7cce837d00c61e8b4730cf7e4c8282bc7ca7 100644 --- a/lib/api/files.rb +++ b/lib/api/files.rb @@ -35,10 +35,9 @@ def assign_file_vars! not_found!('Commit') unless @commit @repo = user_project.repository - @blob = @repo.blob_at(@commit.sha, params[:file_path]) + @blob = @repo.blob_at(@commit.sha, params[:file_path], limit: Gitlab::Git::Blob::LFS_POINTER_MAX_SIZE) not_found!('File') unless @blob - @blob.load_all_data! end def commit_response(attrs) @@ -48,13 +47,21 @@ def commit_response(attrs) } end + def content_sha + Rails.cache.fetch("blob_content_sha256:#{user_project.full_path}:#{@blob.id}") do + @blob.load_all_data! + + Digest::SHA256.hexdigest(@blob.data) + end + end + def blob_data { file_name: @blob.name, file_path: @blob.path, size: @blob.size, encoding: "base64", - content_sha256: Digest::SHA256.hexdigest(@blob.data), + content_sha256: content_sha, ref: params[:ref], blob_id: @blob.id, commit_id: @commit.id, @@ -154,6 +161,8 @@ def blob_data get ":id/repository/files/:file_path", requirements: FILE_ENDPOINT_REQUIREMENTS do assign_file_vars! + @blob.load_all_data! + data = blob_data set_http_headers(data) diff --git a/spec/requests/api/files_spec.rb b/spec/requests/api/files_spec.rb index 869df06b60ceb176abc8acbb596faa4950cc9dd2..0b898496dd620435bfead8210cad9c81d9088c7c 100644 --- a/spec/requests/api/files_spec.rb +++ b/spec/requests/api/files_spec.rb @@ -95,6 +95,19 @@ def route(file_path = nil) expect(response.headers['X-Gitlab-Content-Sha256']).to eq('c440cd09bae50c4632cc58638ad33c6aa375b6109d811e76a9cc3a613c1e8887') end + it 'caches sha256 of the content', :use_clean_rails_redis_caching do + head api(route(file_path), current_user, **options), params: params + + expect(Rails.cache.fetch("blob_content_sha256:#{project.full_path}:#{response.headers['X-Gitlab-Blob-Id']}")) + .to eq('c440cd09bae50c4632cc58638ad33c6aa375b6109d811e76a9cc3a613c1e8887') + + expect_next_instance_of(Gitlab::Git::Blob) do |instance| + expect(instance).not_to receive(:load_all_data!) + end + + head api(route(file_path), current_user, **options), params: params + end + it 'returns file by commit sha' do # This file is deleted on HEAD file_path = "files%2Fjs%2Fcommit%2Ejs%2Ecoffee"