Skip to content

Commit

Permalink
uri encoding the source key in dataspace file copy (#1884)
Browse files Browse the repository at this point in the history
Turns out you need to url encode the key if you put it with the bucket name.
'bucket/key+with+space' needs to be 'bucket/key%2Bwith%2Bspace' for copy_object
even though aws will tell you the key is 'key+with+space'
  • Loading branch information
carolyncole authored Aug 5, 2024
1 parent 72a310f commit c23b248
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 1 deletion.
2 changes: 1 addition & 1 deletion app/services/s3_query_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ def copy_file(source_key:, target_bucket:, target_key:, size:)
if size > part_size
copy_multi_part(source_key:, target_bucket:, target_key:, size:)
else
client.copy_object(copy_source: source_key, bucket: target_bucket, key: target_key, checksum_algorithm: "SHA256")
client.copy_object(copy_source: source_key.gsub("+", "%2B"), bucket: target_bucket, key: target_key, checksum_algorithm: "SHA256")
end
rescue Aws::Errors::ServiceError => aws_service_error
message = "An error was encountered when requesting to copy AWS S3 Object from #{source_key} to #{target_key} in the bucket #{target_bucket}: #{aws_service_error}"
Expand Down
23 changes: 23 additions & 0 deletions spec/services/s3_query_service_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -864,6 +864,29 @@
end
end

describe "#copy_file" do
let(:fake_aws_client) { double(Aws::S3::Client) }
let(:fake_completion) { instance_double(Seahorse::Client::Response, "successful?": true) }

before do
s3_query_service.stub(:client).and_return(fake_aws_client)
fake_aws_client.stub(:copy_object).and_return(fake_completion)
end

it "copies the file calling copy_object" do
expect(s3_query_service.copy_file(target_bucket: "example-bucket-post", source_key: "source-key", target_key: "other-bucket/target-key", size: 23)).to eq(fake_completion)
expect(s3_query_service.client).to have_received(:copy_object).with(bucket: "example-bucket-post", copy_source: "source-key", key: "other-bucket/target-key", checksum_algorithm: "SHA256")
end

context "the filename originally had a space" do
it "it url encode the space and copies the file calling copy_object" do
expect(s3_query_service.copy_file(target_bucket: "example-bucket-post", source_key: "directory/source-key+space", target_key: "other-bucket/target-key", size: 23)).to eq(fake_completion)
expect(s3_query_service.client).to have_received(:copy_object).with(bucket: "example-bucket-post", copy_source: "directory/source-key%2Bspace", key: "other-bucket/target-key",
checksum_algorithm: "SHA256")
end
end
end

context "when there are empty files" do
let(:user) { FactoryBot.create(:user) }
let(:work) { FactoryBot.create(:draft_work, doi:) }
Expand Down

0 comments on commit c23b248

Please sign in to comment.