summaryrefslogtreecommitdiff
path: root/app/controllers
diff options
context:
space:
mode:
authorAhmad Sherif <me@ahmadsherif.com>2019-07-10 19:34:05 +0200
committerAhmad Sherif <me@ahmadsherif.com>2019-07-23 20:37:49 +0200
commit7b76c8d644624f9a8a05e2e7a39af30c0c0c4ae0 (patch)
treee11013ab87b27c5020f10a7471cecea3b15a891d /app/controllers
parent5b669c191d766ab980d647107d7c183be5f8f99e (diff)
downloadgitlab-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')
-rw-r--r--app/controllers/projects/repositories_controller.rb60
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])