class Oss::Client

Attributes

access_key_id[R]
access_key_secret[R]
debug_mode[RW]
endpoint[R]

Public Class Methods

new(endpoint, access_key_id, access_key_secret, debug_mode = false) click to toggle source
# File lib/oss/client.rb, line 16
def initialize(endpoint, access_key_id, access_key_secret, debug_mode = false)
  @debug_mode        = debug_mode
  @endpoint          = endpoint
  @access_key_id     = access_key_id
  @access_key_secret = access_key_secret
end

Public Instance Methods

delete(options = {}) click to toggle source

http delete request

# File lib/oss/client.rb, line 39
def delete(options = {})
  request_prepare(:delete, options)
end
get(options = {}) click to toggle source

http get request

# File lib/oss/client.rb, line 29
def get(options = {})
  request_prepare(:get, options)
end
head(options = {}) click to toggle source

http delete request

# File lib/oss/client.rb, line 44
def head(options = {})
  request_prepare(:head, options)
end
options(options = {}) click to toggle source

http delete request

# File lib/oss/client.rb, line 49
def options(options = {})
  request_prepare(:options, options)
end
post(options = {}) click to toggle source

http post request

# File lib/oss/client.rb, line 34
def post(options = {})
  request_prepare(:post, options)
end
put(options = {}) click to toggle source

http put request

# File lib/oss/client.rb, line 24
def put(options = {})
  request_prepare(:put, options)
end
request(host, path, headers, as = :xml) { |url, headers| ... } click to toggle source
# File lib/oss/client.rb, line 101
def request(host, path, headers, as = :xml, &block)
  url = "http://#{host}#{URI::encode(path)}"

  # send request and rescue errors
  begin
    response = yield(url, headers)
  rescue RestClient::ExceptionWithResponse => err
    response = err.response
  end

  p "DEBUG: response body =======>\n#{response.body}\n" if debug_mode

  if response.code/100 != 2
    # error response
    error_handler(response)
  else
    # success response
    case as
      when :xml
        # parse as xml object
        Nokogiri::XML(response.body)
      when :raw
        # return raw response
        response
      else
        raise 'Undefined request as param!'
    end
  end

end
request_prepare(method, options) click to toggle source
# File lib/oss/client.rb, line 53
def request_prepare(method, options)
  # set header sign
  options[:sign_configs] ||= Hash.new
  options[:sign_configs][:date] = gmt_date
  options[:sign_configs][:host] = options[:host]
  options[:sign_configs][:path] = options[:path]
  options[:sign_configs][:verb] = method.to_s.upcase

  # content md5 check if need
  if options[:content_md5_check]
    # payload make md digest
    md5 = Digest::MD5.digest(options[:payload])

    # then make base64 and trim \n
    cm = Base64.encode64(md5).gsub("\n", '')
    options[:sign_configs][:content_md5] = cm

    # set to header
    options[:headers] ||= Hash.new
    options[:headers]['Content-MD5'] = cm
  end

  # set header content length if need
  if options[:content_length_check]
    options[:payload] ||= ''
    options[:headers]['Content-Length'] = options[:payload].bytesize
  end

  # set get path query string
  path = Util.set_query_string(options[:path], options[:query_string])

  # add query string to sign if need
  if options[:sign_configs][:sign_query_string]
    options[:sign_configs][:path] = path
  end

  # create sign header
  signed_header = set_header_sign(options[:headers], options[:sign_configs])

  # send request
  request(options[:host], path, signed_header, options[:as] || :xml) do |url, header|

    # use RestClient send request
    RestClient::Request.execute(url: url, method: method, headers: header, payload: options[:payload])

  end
end

Private Instance Methods

error_handler(response) click to toggle source
# File lib/oss/client.rb, line 135
def error_handler(response)
  xml_doc  = Nokogiri::XML(response.body)

  # parse all error infos
  error_attrs = {
      http_status: response.code,
      code:        xml_doc.xpath('Error/Code').inner_text,
      message:     xml_doc.xpath('Error/Message').inner_text,
      header:      xml_doc.xpath('Error/Header').inner_text,
      request_id:  xml_doc.xpath('Error/RequestId').inner_text,
      host_id:     xml_doc.xpath('Error/HostId').inner_text
  }

  # error raise format
  status     = "HttpStatus: #{error_attrs[:http_status]}\n"
  code       = "Code: #{error_attrs[:code]}\n"
  message    = "Message: #{error_attrs[:message]}\n"
  header     = error_attrs[:header] == '' ? '' : "Header: #{error_attrs[:header]}\n"
  request_id = "RequestId: #{error_attrs[:request_id]}\n"
  host       = "HostId: #{error_attrs[:host_id]}\n"

  error_info = "\n#{status}#{code}#{message}#{header}#{request_id}#{host}\n"

  # raise error
  raise ResponseError.new(error_attrs, error_info)
end
gmt_date() click to toggle source

create GMT date format

# File lib/oss/client.rb, line 201
def gmt_date
  Time.now.gmtime.strftime("%a, %d %b %Y %H:%M:%S GMT")
end
set_header_sign(origin_header, configs = {}) click to toggle source
# File lib/oss/client.rb, line 162
def set_header_sign(origin_header, configs = {})
  # new hash if not exist
  origin_header = Hash.new if origin_header.nil?

  # set authorization signature header
  origin_header['Authorization'] = signature(
      configs[:verb],
      configs[:date],
      "#{configs[:resource]}#{configs[:path]}",
      configs[:content_md5],
      configs[:content_type],
      configs[:oss_headers]
  )

  # set server headers
  origin_header['Host'] = configs[:host]
  origin_header['Date'] = configs[:date]
  origin_header
end
signature(verb, date, resource = '', content_md5 = '', content_type = '', oss_headers = '') click to toggle source
# File lib/oss/client.rb, line 182
def signature(verb, date, resource = '', content_md5 = '', content_type = '', oss_headers = '')
  # set oss headers like x-oss-something into sign
  oss_headers << "\n" if oss_headers != nil and oss_headers != ''

  # string ready to sign
  string_to_sign = "#{verb}\n#{content_md5}\n#{content_type}\n#{date}\n#{oss_headers}#{resource}"

  p "DEBUG: client sign string =======>\n#{string_to_sign}\n" if debug_mode

  # use hmac-sha1 then base64
  digest = OpenSSL::Digest.new('sha1')
  h = OpenSSL::HMAC.digest(digest, access_key_secret, string_to_sign)
  b = Base64.encode64(h)

  # final signature Authorization value
  "OSS #{access_key_id}:#{b.gsub("\n", '')}"
end