gitlab-org--gitlab-foss/lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb

96 lines
2.6 KiB
Ruby

# frozen_string_literal: true
module Gitlab
module ImportExport
module AfterExportStrategies
class WebUploadStrategy < BaseAfterExportStrategy
PUT_METHOD = 'PUT'
POST_METHOD = 'POST'
INVALID_HTTP_METHOD = 'invalid. Only PUT and POST methods allowed.'
validates :url, addressable_url: true
validate do
unless [PUT_METHOD, POST_METHOD].include?(http_method.upcase)
errors.add(:http_method, INVALID_HTTP_METHOD)
end
end
def initialize(url:, http_method: PUT_METHOD)
super
end
protected
def strategy_execute
log_info(message: "Started uploading project", export_size: export_size)
upload_duration = Benchmark.realtime do
if Feature.enabled?(:import_export_web_upload_stream) && !project.export_file.file_storage?
upload_project_as_remote_stream
else
handle_response_error(send_file)
end
end
log_info(message: "Finished uploading project", export_size: export_size, upload_duration: upload_duration)
end
def handle_response_error(response)
unless response.success?
raise StrategyError, "Error uploading the project. Code #{response.code}: #{response.message}"
end
end
def delete_export?
false
end
private
def send_file
Gitlab::HTTP.public_send(http_method.downcase, url, send_file_options) # rubocop:disable GitlabSecurity/PublicSend
ensure
export_file.close if export_file
end
def upload_project_as_remote_stream
Gitlab::ImportExport::RemoteStreamUpload.new(
download_url: project.export_file.url,
upload_url: url,
options: {
upload_method: http_method.downcase.to_sym,
upload_content_type: 'application/gzip'
}).execute
rescue Gitlab::ImportExport::RemoteStreamUpload::StreamError => e
log_error(message: e.message, response_body: e.response_body.truncate(3000))
raise
end
def export_file
@export_file ||= project.export_file.open
end
def send_file_options
{
body_stream: export_file,
headers: headers
}
end
def headers
{
'Content-Type' => 'application/gzip',
'Content-Length' => export_size.to_s
}
end
def export_size
project.export_file.file.size
end
end
end
end
end