diff options
author | Ahmad Sherif <me@ahmadsherif.com> | 2019-07-10 19:34:05 +0200 |
---|---|---|
committer | Ahmad Sherif <me@ahmadsherif.com> | 2019-07-23 20:37:49 +0200 |
commit | 7b76c8d644624f9a8a05e2e7a39af30c0c0c4ae0 (patch) | |
tree | e11013ab87b27c5020f10a7471cecea3b15a891d /app/controllers/projects/repositories_controller.rb | |
parent | 5b669c191d766ab980d647107d7c183be5f8f99e (diff) | |
download | gitlab-ce-7b76c8d644624f9a8a05e2e7a39af30c0c0c4ae0.tar.gz |
Return an ETag headers for the archive endpointadd-caching-to-archive-endpoint
We use the relative path of the archive to check for archive staleness.
Diffstat (limited to 'app/controllers/projects/repositories_controller.rb')
-rw-r--r-- | app/controllers/projects/repositories_controller.rb | 60 |
1 files changed, 53 insertions, 7 deletions
diff --git a/app/controllers/projects/repositories_controller.rb b/app/controllers/projects/repositories_controller.rb index 3b4215b766e..a51759641e4 100644 --- a/app/controllers/projects/repositories_controller.rb +++ b/app/controllers/projects/repositories_controller.rb @@ -6,6 +6,7 @@ class Projects::RepositoriesController < Projects::ApplicationController # Authorize before_action :require_non_empty_project, except: :create before_action :assign_archive_vars, only: :archive + before_action :assign_append_sha, only: :archive before_action :authorize_download_code! before_action :authorize_admin_project!, only: :create @@ -16,19 +17,64 @@ class Projects::RepositoriesController < Projects::ApplicationController end def archive - append_sha = params[:append_sha] + set_cache_headers + return if archive_not_modified? - if @ref - shortname = "#{@project.path}-#{@ref.tr('/', '-')}" - append_sha = false if @filename == shortname - end - - send_git_archive @repository, ref: @ref, path: params[:path], format: params[:format], append_sha: append_sha + send_git_archive @repository, **repo_params rescue => ex logger.error("#{self.class.name}: #{ex}") git_not_found! end + private + + def repo_params + @repo_params ||= { ref: @ref, path: params[:path], format: params[:format], append_sha: @append_sha } + end + + def set_cache_headers + expires_in cache_max_age(archive_metadata['CommitId']), public: project.public? + fresh_when(etag: archive_metadata['ArchivePath']) + end + + def archive_not_modified? + # Check response freshness (Last-Modified and ETag) + # against request If-Modified-Since and If-None-Match conditions. + request.fresh?(response) + end + + def archive_metadata + @archive_metadata ||= @repository.archive_metadata( + @ref, + '', # Where archives are stored isn't really important for ETag purposes + repo_params[:format], + path: repo_params[:path], + append_sha: @append_sha + ) + end + + def cache_max_age(commit_id) + if @ref == commit_id + # This is a link to an archive by a commit SHA. That means that the archive + # is immutable. The only reason to invalidate the cache is if the commit + # was deleted or if the user lost access to the repository. + Repository::ARCHIVE_CACHE_TIME_IMMUTABLE + else + # A branch or tag points at this archive. That means that the expected archive + # content may change over time. + Repository::ARCHIVE_CACHE_TIME + end + end + + def assign_append_sha + @append_sha = params[:append_sha] + + if @ref + shortname = "#{@project.path}-#{@ref.tr('/', '-')}" + @append_sha = false if @filename == shortname + end + end + def assign_archive_vars if params[:id] @ref, @filename = extract_ref(params[:id]) |