lib/fakes3/server.rb in fakes3-1.2.0 vs lib/fakes3/server.rb in fakes3-1.2.1
- old
+ new
@@ -2,13 +2,15 @@
require 'webrick'
require 'webrick/https'
require 'openssl'
require 'securerandom'
require 'cgi'
+require 'uri'
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'
require 'ipaddr'
@@ -24,10 +26,11 @@
GET_ACL = "GET_ACL"
SET_ACL = "SET_ACL"
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,
:path, :is_path_style, :query, :http_verb
@@ -96,10 +99,11 @@
real_obj = @store.get_object(s_req.bucket, s_req.object, request)
if !real_obj
response.status = 404
response.body = XmlAdapter.error_no_such_key(s_req.object)
response['Content-Type'] = "application/xml"
+ response['Access-Control-Allow-Origin'] = '*'
return
end
if_none_match = request["If-None-Match"]
if if_none_match == "\"#{real_obj.md5}\"" or if_none_match == "*"
@@ -122,12 +126,11 @@
if real_obj.content_encoding
response.header['X-Content-Encoding'] = real_obj.content_encoding
response.header['Content-Encoding'] = real_obj.content_encoding
end
- response['Content-Disposition'] = real_obj.content_disposition if real_obj.content_disposition
- stat = File::Stat.new(real_obj.io.path)
+ response['Content-Disposition'] = real_obj.content_disposition ? real_obj.content_disposition : 'attachment'
response['Last-Modified'] = Time.iso8601(real_obj.modified_date).httpdate
response.header['ETag'] = "\"#{real_obj.md5}\""
response['Accept-Ranges'] = "bytes"
response['Last-Ranges'] = "bytes"
@@ -135,10 +138,11 @@
real_obj.custom_metadata.each do |header, value|
response.header['x-amz-meta-' + header] = value
end
+ stat = File::Stat.new(real_obj.io.path)
content_length = stat.size
# Added Range Query support
range = request.header["range"].first
if range
@@ -166,10 +170,14 @@
response.body = ""
real_obj.io.close
else
response.body = real_obj.io
end
+
+ if real_obj.cache_control
+ response['Cache-Control'] = real_obj.cache_control
+ end
end
end
def do_PUT(request, response)
s_req = normalize_request(request)
@@ -238,10 +246,14 @@
response.status = 200
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 || "")
if query.has_key?('uploads')
@@ -317,10 +329,14 @@
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)
when Request::DELETE_BUCKET
@store.delete_bucket(s_req.bucket)
@@ -330,11 +346,10 @@
response.body = ""
end
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'
response['Access-Control-Expose-Headers'] = 'ETag'
end
@@ -354,14 +369,17 @@
else
elems = path.split("/")
end
if elems.size == 0
- raise UnsupportedOperation
+ s_req.type = Request::DELETE_OBJECTS
+ s_req.query = query
+ s_req.webrick_request = webrick_req
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('/')
s_req.object = object
end
@@ -430,11 +448,12 @@
# TODO: also parse the x-amz-copy-source-range:bytes=first-last header
# for multipart copy
copy_source = webrick_req.header["x-amz-copy-source"]
if copy_source and copy_source.size == 1
- src_elems = copy_source.first.split("/")
+ copy_source = URI.unescape copy_source.first
+ src_elems = copy_source.split("/")
root_offset = src_elems[0] == "" ? 1 : 0
s_req.src_bucket = src_elems[root_offset]
s_req.src_object = src_elems[1 + root_offset,src_elems.size].join("/")
s_req.type = Request::COPY
end
@@ -480,10 +499,14 @@
when 'GET','HEAD'
normalize_get(webrick_req,s_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
validate_request(s_req)