Prefix_delete for cellar
This commit is contained in:
parent
e2c583480d
commit
07134684d4
2 changed files with 111 additions and 9 deletions
|
@ -12,12 +12,11 @@ module ActiveStorage
|
||||||
end
|
end
|
||||||
|
|
||||||
def download(key)
|
def download(key)
|
||||||
|
# TODO: error handling
|
||||||
if block_given?
|
if block_given?
|
||||||
instrument :streaming_download, key: key do
|
instrument :streaming_download, key: key do
|
||||||
http_start do |http|
|
http_start do |http|
|
||||||
request = Net::HTTP::Get.new(URI::join(@endpoint, "/#{key}"))
|
http.request(get_request(key)) do |response|
|
||||||
sign(request, key)
|
|
||||||
http.request(request) do |response|
|
|
||||||
response.read_body do |chunk|
|
response.read_body do |chunk|
|
||||||
yield(chunk.force_encoding(Encoding::BINARY))
|
yield(chunk.force_encoding(Encoding::BINARY))
|
||||||
end
|
end
|
||||||
|
@ -27,9 +26,7 @@ module ActiveStorage
|
||||||
else
|
else
|
||||||
instrument :download, key: key do
|
instrument :download, key: key do
|
||||||
http_start do |http|
|
http_start do |http|
|
||||||
request = Net::HTTP::Get.new(URI::join(@endpoint, "/#{key}"))
|
response = http.request(get_request(key))
|
||||||
sign(request, key)
|
|
||||||
response = http.request(request)
|
|
||||||
if response.is_a?(Net::HTTPSuccess)
|
if response.is_a?(Net::HTTPSuccess)
|
||||||
response.body.force_encoding(Encoding::BINARY)
|
response.body.force_encoding(Encoding::BINARY)
|
||||||
end
|
end
|
||||||
|
@ -39,11 +36,23 @@ module ActiveStorage
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete(key)
|
def delete(key)
|
||||||
|
# TODO: error handling
|
||||||
instrument :delete, key: key do
|
instrument :delete, key: key do
|
||||||
http_start do |http|
|
http_start do |http|
|
||||||
request = Net::HTTP::Delete.new(URI::join(@endpoint, "/#{key}"))
|
perform_delete(http, key)
|
||||||
sign(request, key)
|
end
|
||||||
http.request(request)
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete_prefixed(prefix)
|
||||||
|
# TODO: error handling
|
||||||
|
# TODO: handle pagination if more than 1000 keys
|
||||||
|
instrument :delete_prefixed, prefix: prefix do
|
||||||
|
http_start do |http|
|
||||||
|
list_prefixed(http, prefix).each do |key|
|
||||||
|
# TODO: use bulk delete instead
|
||||||
|
perform_delete(http, key)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -112,5 +121,47 @@ module ActiveStorage
|
||||||
"#{canonicalized_amz_headers}#{canonicalized_resource}"
|
"#{canonicalized_amz_headers}#{canonicalized_resource}"
|
||||||
Base64.encode64(OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha1'), @secret_access_key, string_to_sign)).strip
|
Base64.encode64(OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha1'), @secret_access_key, string_to_sign)).strip
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def list_prefixed(http, prefix)
|
||||||
|
request = Net::HTTP::Get.new(URI::join(@endpoint, "/?list-type=2&prefix=#{prefix}"))
|
||||||
|
sign(request, "")
|
||||||
|
response = http.request(request)
|
||||||
|
if response.is_a?(Net::HTTPSuccess)
|
||||||
|
parse_bucket_listing(response.body)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse_bucket_listing(bucket_listing_xml)
|
||||||
|
doc = Nokogiri::XML(bucket_listing_xml)
|
||||||
|
doc
|
||||||
|
.xpath('//xmlns:Contents/xmlns:Key')
|
||||||
|
.map{ |k| k.text }
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_request(key)
|
||||||
|
request = Net::HTTP::Get.new(URI::join(@endpoint, "/#{key}"))
|
||||||
|
sign(request, key)
|
||||||
|
request
|
||||||
|
end
|
||||||
|
|
||||||
|
def bulk_deletion_request_body(keys)
|
||||||
|
builder = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
|
||||||
|
xml.Delete do
|
||||||
|
xml.Quiet("true")
|
||||||
|
keys.each do |k|
|
||||||
|
xml.Object do
|
||||||
|
xml.Key(k)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
builder.to_xml
|
||||||
|
end
|
||||||
|
|
||||||
|
def perform_delete(http, key)
|
||||||
|
request = Net::HTTP::Delete.new(URI::join(@endpoint, "/#{key}"))
|
||||||
|
sign(request, key)
|
||||||
|
http.request(request)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -112,4 +112,55 @@ describe 'CellarService' do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'parse_bucket_listing' do
|
||||||
|
let(:response) do
|
||||||
|
'<ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
|
||||||
|
<Name>example-bucket</Name>
|
||||||
|
<Prefix></Prefix>
|
||||||
|
<KeyCount>2</KeyCount>
|
||||||
|
<MaxKeys>1000</MaxKeys>
|
||||||
|
<Delimiter>/</Delimiter>
|
||||||
|
<IsTruncated>false</IsTruncated>
|
||||||
|
<Contents>
|
||||||
|
<Key>sample1.jpg</Key>
|
||||||
|
<LastModified>2011-02-26T01:56:20.000Z</LastModified>
|
||||||
|
<ETag>"bf1d737a4d46a19f3bced6905cc8b902"</ETag>
|
||||||
|
<Size>142863</Size>
|
||||||
|
<StorageClass>STANDARD</StorageClass>
|
||||||
|
</Contents>
|
||||||
|
<Contents>
|
||||||
|
<Key>sample2.jpg</Key>
|
||||||
|
<LastModified>2011-02-26T01:56:20.000Z</LastModified>
|
||||||
|
<ETag>"bf1d737a4d46a19f3bced6905cc8b902"</ETag>
|
||||||
|
<Size>142863</Size>
|
||||||
|
<StorageClass>STANDARD</StorageClass>
|
||||||
|
</Contents>
|
||||||
|
</ListBucketResult>'
|
||||||
|
end
|
||||||
|
|
||||||
|
subject { cellar_service.send(:parse_bucket_listing, response) }
|
||||||
|
|
||||||
|
it { is_expected.to eq(["sample1.jpg", "sample2.jpg"]) }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'bulk_deletion_request_body' do
|
||||||
|
let(:expected_response) do
|
||||||
|
'<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Delete>
|
||||||
|
<Quiet>true</Quiet>
|
||||||
|
<Object>
|
||||||
|
<Key>chapi</Key>
|
||||||
|
</Object>
|
||||||
|
<Object>
|
||||||
|
<Key>chapo</Key>
|
||||||
|
</Object>
|
||||||
|
</Delete>
|
||||||
|
'
|
||||||
|
end
|
||||||
|
|
||||||
|
subject { cellar_service.send(:bulk_deletion_request_body, ['chapi', 'chapo']) }
|
||||||
|
|
||||||
|
it { is_expected.to eq(expected_response) }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue