class AWS::S3::Client

Client class for Amazon Simple Storage Service (S3).

def self.bucket_method(method_name, verb, *args, &block)

def self.bucket_method(method_name, verb, *args, &block)
  method_options = (args.pop if args.last.kind_of?(Hash)) || {}
  xml_grammar = (args.pop if args.last.respond_to?(:rules))
  verb = verb.to_s.upcase
  subresource = args.first
  add_client_request_method(method_name) do
    configure_request do |req, options|
      require_bucket_name!(options[:bucket_name])
      req.http_method = verb
      req.bucket = options[:bucket_name]
      req.add_param(subresource) if subresource
      if header_options = method_options[:header_options]
        header_options.each do |(opt, header)|
          if value = options[opt]
            # for backwards compatability we translate canned acls
            # header values from symbols to strings (e.g.
            # :public_read translates to 'public-read')
            value = (opt == :acl ? value.to_s.tr('_', '-') : value)
            req.headers[header] = value
          end
        end
      end
    end
    instance_eval(&block) if block
    if xml_grammar
      parser = Core::XML::Parser.new(xml_grammar.rules)
      process_response do |resp|
        resp.data = parser.parse(resp.http_response.body)
        super(resp)
      end
      simulate_response do |resp|
        resp.data = parser.simulate
        super(resp)
      end
    end
  end
end

def empty_response_body? response_body

def empty_response_body? response_body
  response_body.nil? or response_body == ''
end

def extract_error_details response

def extract_error_details response
  if
    (response.http_response.status >= 300 ||
      response.request_type == :complete_multipart_upload) and
    body = response.http_response.body and
    error = Core::XML::Parser.parse(body) and
    error[:code]
  then
    [error[:code], error[:message]]
  end
end

def extract_object_headers resp

def extract_object_headers resp
  meta = {}
  resp.http_response.headers.each_pair do |name,value|
    if name =~ /^x-amz-meta-(.+)$/i
      meta[$1] = [value].flatten.join
    end
  end
  resp.data[:meta] = meta
  if expiry = resp.http_response.headers['x-amz-expiration']
    expiry.first =~ /^expiry-date="(.+)", rule-id="(.+)"$/
    exp_date = DateTime.parse($1)
    exp_rule_id = $2
  else
    exp_date = nil
    exp_rule_id = nil
  end
  resp.data[:expiration_date] = exp_date if exp_date
  resp.data[:expiration_rule_id] = exp_rule_id if exp_rule_id
  restoring = false
  restore_date = nil
  if restore = resp.http_response.headers['x-amz-restore']
    if restore.first =~ /ongoing-request="(.+?)", expiry-date="(.+?)"/
      restoring = $1 == "true"
      restore_date = $2 && DateTime.parse($2)
    elsif restore.first =~ /ongoing-request="(.+?)"/
      restoring = $1 == "true"
    end
  end
  resp.data[:restore_in_progress] = restoring
  resp.data[:restore_expiration_date] = restore_date if restore_date
  {
    'x-amz-version-id' => :version_id,
    'content-type' => :content_type,
    'content-encoding' => :content_encoding,
    'cache-control' => :cache_control,
    'expires' => :expires,
    'etag' => :etag,
    'x-amz-website-redirect-location' => :website_redirect_location,
    'accept-ranges' => :accept_ranges,
  }.each_pair do |header,method|
    if value = resp.http_response.header(header)
      resp.data[method] = value
    end
  end
  if time = resp.http_response.header('Last-Modified')
    resp.data[:last_modified] = Time.parse(time)
  end
  if length = resp.http_response.header('content-length')
    resp.data[:content_length] = length.to_i
  end
  if sse = resp.http_response.header('x-amz-server-side-encryption')
    resp.data[:server_side_encryption] = sse.downcase.to_sym
  end
end

def failed_multipart_upload? response

At that time it sends an XML message with success or failure.
and then start streaming whitespace until it knows the final result.
S3 may return a 200 response code in response to complete_multipart_upload
def failed_multipart_upload? response
  response.request_type == :complete_multipart_upload &&
  extract_error_details(response)
end

def is_xml? possible_xml

Returns:
  • (Boolean) - Returns `true` if the given string is a valid xml

Parameters:
  • possible_xml (String) --
def is_xml? possible_xml
  begin
    REXML::Document.new(possible_xml).has_elements?
  rescue
    false
  end
end

def md5 str

def md5 str
  Base64.encode64(Digest::MD5.digest(str)).strip
end

def move_access_control_policy options

method now is to pass :access_control_policy an xml document.
as a string or an object that responds to #to_xml. The prefered
Previously the access control policy could be specified via :acl
def move_access_control_policy options
  if acl = options[:acl]
    if acl.is_a?(String) and is_xml?(acl)
      options[:access_control_policy] = options.delete(:acl)
    elsif acl.respond_to?(:to_xml)
      options[:access_control_policy] = options.delete(:acl).to_xml
    end
  end
end

def new_request

def new_request
  req = S3::Request.new
  req.force_path_style = config.s3_force_path_style?
  req
end

def parse_copy_part_response resp

def parse_copy_part_response resp
  doc = REXML::Document.new(resp.http_response.body)
  resp[:etag] = doc.root.elements["ETag"].text
  resp[:last_modified] = doc.root.elements["LastModified"].text
  if header = resp.http_response.headers['x-amzn-requestid']
    data[:request_id] = [header].flatten.first
  end
end

def populate_error resp

HTTP spec. We have to detect these errors specially.
yet still be errors. These return empty bodies to comply with the
There are a few of s3 requests that can generate empty bodies and
def populate_error resp
  code = resp.http_response.status
  if EMPTY_BODY_ERRORS.include?(code) and empty_response_body?(resp.http_response.body)
    error_class = EMPTY_BODY_ERRORS[code]
    resp.error = error_class.new(resp.http_request, resp.http_response)
  else
    super
  end
end

def retryable_error? response

def retryable_error? response
  super or
  failed_multipart_upload?(response) or
  response.error.is_a?(Errors::RequestTimeout)
end