module EC2::Common::HTTP

Constants

DEFAULT_REGION
DEFAULT_SIGV

Public Class Methods

delete(url, bucket, options={}, user=nil, pass=nil, debug=false, sigv=DEFAULT_SIGV, region=DEFAULT_REGION) click to toggle source
# File lib/ec2/common/http.rb, line 128
def HTTP::delete(url, bucket, options={}, user=nil, pass=nil, debug=false, sigv=DEFAULT_SIGV, region=DEFAULT_REGION)
  raise ArgumentError.new('Bad options in HTTP::delete') unless options.is_a? Hash
  begin
    output = Tempfile.new('ec2-delete-response')
    output.close
    
    arguments = ['-X DELETE']
    arguments << get_arguments(url, bucket, 'DELETE', options, user, pass, sigv, region)
    arguments << '-o ' + output.path
    
    response = HTTP::invoke(url, arguments, output.path, debug)
    return EC2::Common::HTTP::Response.new(response.code, response.type)
  ensure
    output.close(true)
    GC.start
  end
end
get(url, bucket, path=nil, options={}, user=nil, pass=nil, size=nil, digest=nil, debug=false, sigv=DEFAULT_SIGV, region=DEFAULT_REGION) click to toggle source
# File lib/ec2/common/http.rb, line 238
def HTTP::get(url, bucket, path=nil, options={}, user=nil, pass=nil, 
              size=nil, digest=nil, debug=false, sigv=DEFAULT_SIGV, region=DEFAULT_REGION)
  raise ArgumentError.new('Bad options in HTTP::get') unless options.is_a? Hash
  buffer = nil
  if path.nil?
    buffer = Tempfile.new('ec2-get-response')
    buffer.close
    path = buffer.path
  else
    directory = File.dirname(path)
    FileUtils.mkdir_p(directory) unless File.exist?(directory)
  end
 
  arguments = [get_arguments(url, bucket, 'GET', options, user, pass, sigv, region)]
  arguments << "--max-filesize #{size}" if size
  arguments << '-o ' + path
  
  begin
    FileUtils.touch path
    response = HTTP::invoke(url, arguments, path, debug)
    body = nil
    if response.success?
      if digest
        obtained = IO.popen("openssl sha1 #{path}") { |io| io.readline.split(/\s+/).last.strip }
        unless digest == obtained                
          File.delete(path) if File.exists?(path) and not buffer.is_a? Tempfile
          raise Error::BadDigest.new(path, digest, obtained)
        end
      end
      if buffer.is_a? Tempfile
        buffer.open; 
        body = buffer.read
      end
    else
      File.delete(path) if File.exist?(path) and not buffer.is_a? Tempfile
    end
    return EC2::Common::HTTP::Response.new(response.code, response.type, body)
  rescue Error::Transfer => e
    File::delete(path) if File::exist?(path) and not buffer.is_a? Tempfile
    raise Error::Retrieve.new(e.message, e.code)
  ensure
    if buffer.is_a? Tempfile
      buffer.close
      buffer.unlink if File.exists? path
      GC.start
    end
  end
end
head(url, bucket, options={}, user=nil, pass=nil, debug=false, sigv=DEFAULT_SIGV, region=DEFAULT_REGION) click to toggle source
# File lib/ec2/common/http.rb, line 290
def HTTP::head(url, bucket, options={}, user=nil, pass=nil, debug=false, sigv=DEFAULT_SIGV, region=DEFAULT_REGION)
  raise ArgumentError.new('Bad options in HTTP::head') unless options.is_a? Hash
  begin
    output = Tempfile.new('ec2-head-response')
    output.close
    
    arguments = ['--head']
    arguments << get_arguments(url, bucket, 'HEAD', options, user, pass, sigv, region)
    arguments << '-o ' + output.path
    
    response = HTTP::invoke(url, arguments, output.path, debug)
    return EC2::Common::HTTP::Response.new(response.code, response.type)
    
  rescue Error::Transfer => e
    raise Error::Retrieve.new(e.message, e.code)
  ensure
    output.close(true)
    GC.start
  end
end
invoke(url, arguments, outfile, debug=false) click to toggle source
# File lib/ec2/common/http.rb, line 72
def HTTP::invoke(url, arguments, outfile, debug=false)
  begin
    raise ArgumentError.new(outfile) unless File.exists? outfile
    result = EC2::Common::Curl.execute("#{arguments.join(' ')} '#{url}'", debug)
    if result.success?
      if result.response.success?
        return result.response
      else
        synopsis= 'Server.Error(' + result.response.code.to_s + '): '
        message = result.stderr + ' '
        if result.response.type == 'application/xml'                
          require 'rexml/document'
          doc = REXML::Document.new(IO.read(outfile))
          if doc.root
            if result.response.redirect?
              endpoint = REXML::XPath.first(doc, '/Error/Endpoint').text
              raise Error::Redirect.new(result.response.code, endpoint)
            end
            content = REXML::XPath.first(doc, '/Error/Code')
            unless content.nil? or content.text.empty?
              synopsis= 'Server.'+ content.text + '(' + 
                result.response.code.to_s + '): '
            end
            content = REXML::XPath.first(doc, '/Error/Message')
            message = content.text unless content.nil?
          end
        else
          if result.response.type =~ /text/
            message << IO.read(outfile)
          end
        end
        raise Error::Transfer.new(synopsis + message, result.response.code)
      end
    else
      synopsis= 'Curl.Error(' + result.status.to_s + '): '
      message = result.stderr.split("\n").map { |line|            
        if (m = /^curl:\s+(?:\(\d{1,2}\)\s+)*(.*)$/.match(line))
          (m.captures[0] == "try 'curl --help' for more information") ? 
            '' : m.captures[0]
        else
          line.strip
        end
      }.join("\n")
      output = result.stdout.chomp
      if debug and not output.empty?
        message << "\nCurl.Output: " + output.gsub("\n", "\nCurl.Output: ")
      end
      raise Error::Transfer.new(synopsis + message.strip + '.', result.status)
    end
  rescue EC2::Common::Curl::Error => e
    raise Error::Transfer.new(e.message, e.code)
  end
end
put(url, bucket, path, options={}, user=nil, pass=nil, debug=false, sigv=DEFAULT_SIGV, region=DEFAULT_REGION) click to toggle source
# File lib/ec2/common/http.rb, line 151
def HTTP::put(url, bucket, path, options={}, user=nil, pass=nil, debug=false, sigv=DEFAULT_SIGV, region=DEFAULT_REGION)
  path ||= "/dev/null"
  raise Error::PathInvalid.new(path) unless path and File::exist?(path)
  raise ArgumentError.new('Bad options in HTTP::put') unless options.is_a? Hash
  
  begin
    output = Tempfile.new('ec2-put-response')
    output.close

    arguments = [get_arguments(url, bucket, 'PUT', options, user, pass, sigv, region, open(path))]
    arguments << '-T ' + path
    arguments << '-o ' + output.path

    response = HTTP::invoke(url, arguments, output.path, debug)
    return EC2::Common::HTTP::Response.new(response.code, response.type)
  ensure
    output.close(true)
    GC.start
  end
end
putdir(url, bucket, constraint, options={}, user=nil, pass=nil, debug=false, sigv=DEFAULT_SIGV, region=DEFAULT_REGION) click to toggle source
# File lib/ec2/common/http.rb, line 177
def HTTP::putdir(url, bucket, constraint, options={}, user=nil, pass=nil, debug=false, sigv=DEFAULT_SIGV, region=DEFAULT_REGION)
  if constraint and File::exists?(constraint)
    putdir_file(url, bucket, constraint, options, user, pass, debug)
  else
    putdir_binary_data(url, bucket, constraint, options, user, pass, debug, sigv, region)
  end
end
putdir_binary_data(url, bucket, binary_data, options={}, user=nil, pass=nil, debug=false, sigv=DEFAULT_SIGV, region=DEFAULT_REGION) click to toggle source
# File lib/ec2/common/http.rb, line 211
def HTTP::putdir_binary_data(url, bucket, binary_data, options={}, user=nil, pass=nil, debug=false, sigv=DEFAULT_SIGV, region=DEFAULT_REGION)
  raise ArgumentError.new('Bad options in HTTP::putdir_binary_data') unless options.is_a? Hash
  
  begin
    output = Tempfile.new('ec2-put-response')
    output.close
    
    arguments = ["-X PUT"]
    arguments << "--data-binary \"#{binary_data}\""
    arguments << get_arguments(url, bucket, 'PUT', options, user, pass, sigv, region, binary_data)
    arguments << '-o ' + output.path

    response = HTTP::invoke(url, arguments, output.path, debug)
    return EC2::Common::HTTP::Response.new(response.code, response.type)          
  ensure
    output.close(true)
    GC.start
  end
end
putdir_file(url, bucket, path, options={}, user=nil, pass=nil, debug=false) click to toggle source
# File lib/ec2/common/http.rb, line 185
def HTTP::putdir_file(url, bucket, path, options={}, user=nil, pass=nil, debug=false)
  raise Error::PathInvalid.new(path) unless path and File::exist?(path)
  raise ArgumentError.new('Bad options in HTTP::putdir_file') unless options.is_a? Hash

  begin
    output = Tempfile.new('ec2-put-response')
    output.close
    arguments = []

    headers = EC2::Common::Headers.new('PUT')
    options.each do |name, value| headers.add(name, value) end
    headers.sign(user, pass, url, bucket) if user and pass
    
    arguments << headers.get.map { |name, value| "-H \"#{name}:#{value}\""}.join(' ')
    arguments << '-T - '
    arguments << '-o ' + output.path
    arguments << " < #{path}"

    response = HTTP::invoke(url, arguments, output.path, debug)
    return EC2::Common::HTTP::Response.new(response.code, response.type)
  ensure
    output.close(true)
    GC.start
  end
end

Private Class Methods

get_arguments(url, bucket, http_method, options, user, pass, sigv, region, file_path=nil) click to toggle source
# File lib/ec2/common/http.rb, line 312
def HTTP::get_arguments(url, bucket, http_method, options, user, pass, sigv, region, file_path=nil)
  headers = if user and pass
    if sigv == EC2::Common::SIGV2
      EC2::Common::Signature::curl_args_sigv2(url, bucket,
                                              http_method,
                                              options,
                                              user, pass)
    elsif sigv == EC2::Common::SIGV4
      EC2::Common::Signature::curl_args_sigv4(url, region, bucket,
                                              http_method,
                                              options,
                                              user, pass,
                                              file_path)
    end
  else
    options
  end
  headers.map { |name, value| "-H \"#{name}:#{value}\""}.join(' ')
end