Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/lib/gitlab/import_export/remote_stream_upload_spec.rb')
-rw-r--r--spec/lib/gitlab/import_export/remote_stream_upload_spec.rb232
1 files changed, 232 insertions, 0 deletions
diff --git a/spec/lib/gitlab/import_export/remote_stream_upload_spec.rb b/spec/lib/gitlab/import_export/remote_stream_upload_spec.rb
new file mode 100644
index 00000000000..b1bc6b7eeaf
--- /dev/null
+++ b/spec/lib/gitlab/import_export/remote_stream_upload_spec.rb
@@ -0,0 +1,232 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::ImportExport::RemoteStreamUpload do
+ include StubRequests
+
+ subject do
+ described_class.new(
+ download_url: download_url,
+ upload_url: upload_url,
+ options: {
+ upload_method: upload_method,
+ upload_content_type: upload_content_type
+ }
+ )
+ end
+
+ let(:download_url) { 'http://object-storage/file.txt' }
+ let(:upload_url) { 'http://example.com/file.txt' }
+ let(:upload_method) { :post }
+ let(:upload_content_type) { 'text/plain' }
+
+ describe '#execute' do
+ context 'when download request and upload request return 200' do
+ it 'uploads the downloaded content' do
+ stub_request(:get, download_url).to_return(status: 200, body: 'ABC', headers: { 'Content-Length' => 3 })
+ stub_request(:post, upload_url)
+
+ subject.execute
+
+ expect(
+ a_request(:post, upload_url).with(
+ body: 'ABC', headers: { 'Content-Length' => 3, 'Content-Type' => 'text/plain' }
+ )
+ ).to have_been_made
+ end
+ end
+
+ context 'when upload method is put' do
+ let(:upload_method) { :put }
+
+ it 'uploads using the put method' do
+ stub_request(:get, download_url).to_return(status: 200, body: 'ABC', headers: { 'Content-Length' => 3 })
+ stub_request(:put, upload_url)
+
+ subject.execute
+
+ expect(
+ a_request(:put, upload_url).with(
+ body: 'ABC', headers: { 'Content-Length' => 3, 'Content-Type' => 'text/plain' }
+ )
+ ).to have_been_made
+ end
+ end
+
+ context 'when download request does not return 200' do
+ it do
+ stub_request(:get, download_url).to_return(status: 404)
+
+ expect { subject.execute }.to raise_error(
+ Gitlab::ImportExport::RemoteStreamUpload::StreamError,
+ "Invalid response code while downloading file. Code: 404"
+ )
+ end
+ end
+
+ context 'when upload request does not returns 200' do
+ it do
+ stub_request(:get, download_url).to_return(status: 200, body: 'ABC', headers: { 'Content-Length' => 3 })
+ stub_request(:post, upload_url).to_return(status: 403)
+
+ expect { subject.execute }.to raise_error(
+ Gitlab::ImportExport::RemoteStreamUpload::StreamError,
+ "Invalid response code while uploading file. Code: 403"
+ )
+ end
+ end
+
+ context 'when download URL is a local address' do
+ let(:download_url) { 'http://127.0.0.1/file.txt' }
+
+ before do
+ stub_request(:get, download_url)
+ stub_request(:post, upload_url)
+ end
+
+ it 'raises error' do
+ expect { subject.execute }.to raise_error(
+ Gitlab::HTTP::BlockedUrlError,
+ "URL 'http://127.0.0.1/file.txt' is blocked: Requests to localhost are not allowed"
+ )
+ end
+
+ context 'when local requests are allowed' do
+ before do
+ stub_application_setting(allow_local_requests_from_web_hooks_and_services: true)
+ end
+
+ it 'raises does not error' do
+ expect { subject.execute }.not_to raise_error
+ end
+ end
+ end
+
+ context 'when download URL is a local network' do
+ let(:download_url) { 'http://172.16.0.0/file.txt' }
+
+ before do
+ stub_request(:get, download_url)
+ stub_request(:post, upload_url)
+ end
+
+ it 'raises error' do
+ expect { subject.execute }.to raise_error(
+ Gitlab::HTTP::BlockedUrlError,
+ "URL 'http://172.16.0.0/file.txt' is blocked: Requests to the local network are not allowed"
+ )
+ end
+
+ context 'when local network requests are allowed' do
+ before do
+ stub_application_setting(allow_local_requests_from_web_hooks_and_services: true)
+ end
+
+ it 'raises does not error' do
+ expect { subject.execute }.not_to raise_error
+ end
+ end
+ end
+
+ context 'when upload URL is a local address' do
+ let(:upload_url) { 'http://127.0.0.1/file.txt' }
+
+ before do
+ stub_request(:get, download_url)
+ stub_request(:post, upload_url)
+ end
+
+ it 'raises error' do
+ stub_request(:get, download_url)
+
+ expect { subject.execute }.to raise_error(
+ Gitlab::HTTP::BlockedUrlError,
+ "URL 'http://127.0.0.1/file.txt' is blocked: Requests to localhost are not allowed"
+ )
+ end
+
+ context 'when local requests are allowed' do
+ before do
+ stub_application_setting(allow_local_requests_from_web_hooks_and_services: true)
+ end
+
+ it 'raises does not error' do
+ expect { subject.execute }.not_to raise_error
+ end
+ end
+ end
+
+ context 'when upload URL it is a request to local network' do
+ let(:upload_url) { 'http://172.16.0.0/file.txt' }
+
+ before do
+ stub_request(:get, download_url)
+ stub_request(:post, upload_url)
+ end
+
+ it 'raises error' do
+ expect { subject.execute }.to raise_error(
+ Gitlab::HTTP::BlockedUrlError,
+ "URL 'http://172.16.0.0/file.txt' is blocked: Requests to the local network are not allowed"
+ )
+ end
+
+ context 'when local network requests are allowed' do
+ before do
+ stub_application_setting(allow_local_requests_from_web_hooks_and_services: true)
+ end
+
+ it 'raises does not error' do
+ expect { subject.execute }.not_to raise_error
+ end
+ end
+ end
+
+ context 'when upload URL resolves to a local address' do
+ let(:upload_url) { 'http://example.com/file.txt' }
+
+ it 'raises error' do
+ stub_request(:get, download_url)
+ stub_full_request(upload_url, ip_address: '127.0.0.1', method: upload_method)
+
+ expect { subject.execute }.to raise_error(
+ Gitlab::HTTP::BlockedUrlError,
+ "URL 'http://example.com/file.txt' is blocked: Requests to localhost are not allowed"
+ )
+ end
+ end
+ end
+
+ describe Gitlab::ImportExport::RemoteStreamUpload::ChunkStream do
+ describe 'StringIO#copy_stream compatibility' do
+ it 'copies all chunks' do
+ chunks = %w[ABC EFD].to_enum
+ chunk_stream = described_class.new(chunks)
+ new_stream = StringIO.new
+
+ IO.copy_stream(chunk_stream, new_stream)
+ new_stream.rewind
+
+ expect(new_stream.read).to eq('ABCEFD')
+ end
+
+ context 'with chunks smaller and bigger than buffer size' do
+ before do
+ stub_const('Gitlab::ImportExport::RemoteStreamUpload::ChunkStream::DEFAULT_BUFFER_SIZE', 4)
+ end
+
+ it 'copies all chunks' do
+ chunks = %w[A BC DEF GHIJ KLMNOPQ RSTUVWXYZ].to_enum
+ chunk_stream = described_class.new(chunks)
+ new_stream = StringIO.new
+
+ IO.copy_stream(chunk_stream, new_stream)
+ new_stream.rewind
+
+ expect(new_stream.read).to eq('ABCDEFGHIJKLMNOPQRSTUVWXYZ')
+ end
+ end
+ end
+ end
+end