diff --git a/.gitignore b/.gitignore index 6433bbd4..d916a940 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,5 @@ test_root Gemfile.lock .DS_Store +.rvmrc +root/* diff --git a/Gemfile b/Gemfile index 4372cf21..d325047a 100644 --- a/Gemfile +++ b/Gemfile @@ -1,3 +1,3 @@ source 'https://rubygems.org' # Specify your gem's dependencies in fakes3.gemspec -gemspec +gemspec \ No newline at end of file diff --git a/Gemfile.lock b/Gemfile.lock index b39bf03d..2788ab04 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -4,6 +4,7 @@ PATH fakes3 (1.2.0) builder thor + xml-simple GEM remote: https://rubygems.org/ diff --git a/fakes3.gemspec b/fakes3.gemspec index 82747f78..5db3dab0 100644 --- a/fakes3.gemspec +++ b/fakes3.gemspec @@ -26,6 +26,7 @@ Gem::Specification.new do |s| #s.add_development_dependency "debugger" s.add_dependency "thor" s.add_dependency "builder" + s.add_dependency "xml-simple" s.files = `git ls-files`.split("\n") s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") diff --git a/lib/fakes3/file_store.rb b/lib/fakes3/file_store.rb index e6dd1340..de09b18a 100644 --- a/lib/fakes3/file_store.rb +++ b/lib/fakes3/file_store.rb @@ -269,6 +269,23 @@ def delete_object(bucket,object_name,request) end end + def delete_objects(bucket, objects, request) + begin + filenames = [] + objects.each do |object_name| + filenames << File.join(@root,bucket.name,object_name) + object = bucket.find(object_name) + bucket.remove(object) + end + + FileUtils.rm_rf(filenames) + rescue + puts $! + $!.backtrace.each { |line| puts line } + return nil + end + end + # TODO: abstract getting meta data from request. def create_metadata(content, request) metadata = {} diff --git a/lib/fakes3/server.rb b/lib/fakes3/server.rb index 872a5dd0..924c8269 100644 --- a/lib/fakes3/server.rb +++ b/lib/fakes3/server.rb @@ -7,6 +7,7 @@ require 'fakes3/util' require 'fakes3/file_store' require 'fakes3/xml_adapter' +require 'fakes3/xml_parser' require 'fakes3/bucket_query' require 'fakes3/unsupported_operation' require 'fakes3/errors' @@ -26,6 +27,7 @@ class Request MOVE = "MOVE" DELETE_OBJECT = "DELETE_OBJECT" DELETE_BUCKET = "DELETE_BUCKET" + DELETE_OBJECTS = "DELETE_OBJECTS" attr_accessor :bucket, :object, :type, :src_bucket, :src_object, :method, :webrick_request, @@ -162,6 +164,7 @@ def do_GET(request, response) end end response['Content-Length'] = File::Stat.new(real_obj.io.path).size + response['Content-Disposition'] = 'attachment' if s_req.http_verb == 'HEAD' response.body = "" real_obj.io.close @@ -240,6 +243,10 @@ def do_multipartPUT(request, response) end def do_POST(request,response) + if request.query_string === 'delete' + return do_DELETE(request, response) + end + s_req = normalize_request(request) key = request.query['key'] query = CGI::parse(request.request_uri.query || "") @@ -319,6 +326,10 @@ def do_DELETE(request, response) s_req = normalize_request(request) case s_req.type + when Request::DELETE_OBJECTS + bucket_obj = @store.get_bucket(s_req.bucket) + keys = XmlParser.delete_objects(s_req.webrick_request) + @store.delete_objects(bucket_obj,keys,s_req.webrick_request) when Request::DELETE_OBJECT bucket_obj = @store.get_bucket(s_req.bucket) @store.delete_object(bucket_obj,s_req.object,s_req.webrick_request) @@ -332,7 +343,6 @@ def do_DELETE(request, response) def do_OPTIONS(request, response) super - response['Access-Control-Allow-Origin'] = '*' response['Access-Control-Allow-Methods'] = 'PUT, POST, HEAD, GET, OPTIONS' response['Access-Control-Allow-Headers'] = 'Accept, Content-Type, Authorization, Content-Length, ETag, X-CSRF-Token, Content-Disposition' @@ -358,8 +368,9 @@ def normalize_delete(webrick_req, s_req) if elems.size == 0 raise UnsupportedOperation elsif elems.size == 1 - s_req.type = Request::DELETE_BUCKET + s_req.type = webrick_req.query_string == 'delete' ? Request::DELETE_OBJECTS : Request::DELETE_BUCKET s_req.query = query + s_req.webrick_request = webrick_req else s_req.type = Request::DELETE_OBJECT object = elems[1,elems.size].join('/') @@ -482,7 +493,11 @@ def normalize_request(webrick_req) when 'DELETE' normalize_delete(webrick_req,s_req) when 'POST' - normalize_post(webrick_req,s_req) + if webrick_req.query_string != 'delete' + normalize_post(webrick_req,s_req) + else + normalize_delete(webrick_req,s_req) + end else raise "Unknown Request" end diff --git a/lib/fakes3/xml_parser.rb b/lib/fakes3/xml_parser.rb new file mode 100644 index 00000000..da54f8f3 --- /dev/null +++ b/lib/fakes3/xml_parser.rb @@ -0,0 +1,16 @@ +require 'xmlsimple' + +module FakeS3 + class XmlParser + def self.delete_objects(request) + keys = [] + + objects = XmlSimple.xml_in(request.body, {'NoAttr' => true})['Object'] + objects.each do |key| + keys << key['Key'][0] + end + + keys + end + end +end \ No newline at end of file