96 lines
2.6 KiB
Ruby
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
|