#:stopdoc: module AWS module S3 class Base class Response < String attr_reader :response, :body, :parsed def initialize(response) @response = response @body = response.body.to_s super(body) end def headers headers = {} response.each do |header, value| headers[header] = value end headers end memoized :headers def [](header) headers[header] end def each(&block) headers.each(&block) end def code response.code.to_i end {:success => 200..299, :redirect => 300..399, :client_error => 400..499, :server_error => 500..599}.each do |result, code_range| class_eval(<<-EVAL, __FILE__, __LINE__) def #{result}? return false unless response (#{code_range}).include? code end EVAL end def error? !success? && response['content-type'] == 'application/xml' && parsed.root == 'error' end def error Error.new(parsed, self) end memoized :error def parsed # XmlSimple is picky about what kind of object it parses, so we pass in body rather than self Parsing::XmlParser.new(body) end memoized :parsed def inspect "#<%s:0x%s %s %s>" % [self.class, object_id, response.code, response.message] end end end class Bucket class Response < Base::Response def bucket parsed end end end class S3Object class Response < Base::Response def etag headers['etag'][1...-1] end end end class Service class Response < Base::Response def empty? parsed['buckets'].nil? end def buckets parsed['buckets']['bucket'] || [] end end end module ACL class Policy class Response < Base::Response alias_method :policy, :parsed end end end # Requests whose response code is between 300 and 599 and contain an in their body # are wrapped in an Error::Response. This Error::Response contains an Error object which raises an exception # that corresponds to the error in the response body. The exception object contains the ErrorResponse, so # in all cases where a request happens, you can rescue ResponseError and have access to the ErrorResponse and # its Error object which contains information about the ResponseError. # # begin # Bucket.create(..) # rescue ResponseError => exception # exception.response # # => # exception.response.error # # => # end class Error class Response < Base::Response def error? true end def inspect "#<%s:0x%s %s %s: '%s'>" % [self.class.name, object_id, response.code, error.code, error.message] end end end # Guess response class name from current class name. If the guessed response class doesn't exist # do the same thing to the current class's parent class, up the inheritance heirarchy until either # a response class is found or until we get to the top of the heirarchy in which case we just use # the the Base response class. # # Important: This implemantation assumes that the Base class has a corresponding Base::Response. class FindResponseClass #:nodoc: class << self def for(start) new(start).find end end def initialize(start) @container = AWS::S3 @current_class = start end def find self.current_class = current_class.superclass until response_class_found? target.const_get(class_to_find) end private attr_reader :container attr_accessor :current_class def target container.const_get(current_name) end def target? container.const_defined?(current_name) end def response_class_found? target? && target.const_defined?(class_to_find) end def class_to_find :Response end def current_name truncate(current_class) end def truncate(klass) klass.name[/[^:]+$/] end end end end #:startdoc: