class AliyunSDKCore::ROAClient

Attributes

access_key_id[RW]
access_key_secret[RW]
api_version[RW]
endpoint[RW]
hostname[RW]
opts[RW]
security_token[RW]

Public Class Methods

new(config) click to toggle source
# File lib/aliyunsdkcore/roa_client.rb, line 20
def initialize(config)
  validate config

  self.endpoint          = config[:endpoint]
  self.api_version       = config[:api_version]
  self.access_key_id     = config[:access_key_id]
  self.access_key_secret = config[:access_key_secret]
  self.security_token    = config[:security_token]
end

Public Instance Methods

connection(adapter = Faraday.default_adapter) click to toggle source
# File lib/aliyunsdkcore/roa_client.rb, line 72
def connection(adapter = Faraday.default_adapter)
  Faraday.new(:url => self.endpoint) { |faraday| faraday.adapter adapter }
end
default_headers() click to toggle source
# File lib/aliyunsdkcore/roa_client.rb, line 92
def default_headers
  default_headers = {
    'accept' =>                  'application/json',
    'date' =>                    Time.now.httpdate,
    'host' =>                    URI(self.endpoint).host,
    'x-acs-signature-nonce' =>   SecureRandom.hex(16),
    'x-acs-signature-method' =>  'HMAC-SHA1',
    'x-acs-signature-version' => '1.0',
    'x-acs-version' =>           self.api_version,
    'x-sdk-client' =>            "RUBY(#{RUBY_VERSION})", # FIXME: 如何获取Gem的名称和版本号
    'user-agent' =>              DEFAULT_UA
  }
  if self.security_token
    default_headers.merge!(
      'x-acs-accesskey-id'   => self.access_key_id,
      'x-acs-security-token' => self.security_token
    )
  end
  default_headers
end
delete(uri: '', headers: {}, params: {}, options: {}) click to toggle source
# File lib/aliyunsdkcore/roa_client.rb, line 88
def delete(uri: '', headers: {}, params: {}, options: {})
  request(method: :delete, uri: uri, params: params, body: {}, headers: headers, options: options)
end
get(uri: '', headers: {}, params: {}, options: {}) click to toggle source
# File lib/aliyunsdkcore/roa_client.rb, line 76
def get(uri: '', headers: {}, params: {}, options: {})
  request(method: :get, uri: uri, params: params, body: {}, headers: headers, options: options)
end
post(uri: '', headers: {}, params: {}, body: {}, options: {}) click to toggle source
# File lib/aliyunsdkcore/roa_client.rb, line 80
def post(uri: '', headers: {}, params: {}, body: {}, options: {})
  request(method: :post, uri: uri, params: params, body: body, headers: headers, options: options)
end
put(uri: '', headers: {}, params: {}, body: {}, options: {}) click to toggle source
# File lib/aliyunsdkcore/roa_client.rb, line 84
def put(uri: '', headers: {}, params: {}, body: {}, options: {})
  request(method: :put, uri: uri, params: params, body: body, headers: headers, options: options)
end
request(method:, uri:, params: {}, body: {}, headers: {}, options: {}) click to toggle source
# File lib/aliyunsdkcore/roa_client.rb, line 30
def request(method:, uri:, params: {}, body: {}, headers: {}, options: {})
  # :"Content-Type" => "application/json" to "content-type" => "application/json"
  headers.deep_transform_keys! { |key| key.to_s.downcase }
  mix_headers = default_headers.merge(headers)

  response = connection.send(method.downcase) do |request|
    request.url uri, params
    if body
      if mix_headers['content-type'].start_with? 'application/json'
        request_body = body.to_json
      elsif mix_headers['content-type'].start_with? 'application/x-www-form-urlencoded'
        request_body = URI.encode_www_form(body)
      else
        request_body = body
      end
      mix_headers['content-md5']    = Digest::MD5.base64digest request_body
      mix_headers['content-length'] = request_body.length.to_s
      request.body                  = request_body
    end
    string2sign = string_to_sign(method, uri, mix_headers, params)
    mix_headers.merge!(authorization: authorization(string2sign))
    mix_headers.each { |key, value| request.headers[key] = value }
  end

  return response if options.has_key? :raw_body

  response_content_type = response.headers['Content-Type'] || ''
  if response_content_type.start_with?('application/json')
    if response.status >= 400
      result = JSON.parse(response.body)
      raise StandardError, "code: #{response.status}, #{result['Message']} requestid: #{result['RequestId']}"
    end
  end

  if response_content_type.start_with?('text/xml')
    result = Hash.from_xml(response.body)
    raise ACSError, result['Error'] if result['Error']
  end

  response
end

Private Instance Methods

authorization(string_to_sign) click to toggle source
# File lib/aliyunsdkcore/roa_client.rb, line 136
def authorization(string_to_sign)
  "acs #{self.access_key_id}:#{signature(string_to_sign)}"
end
canonicalized_headers(headers) click to toggle source
# File lib/aliyunsdkcore/roa_client.rb, line 126
def canonicalized_headers(headers)
  headers.keys.select { |key| key.to_s.start_with? 'x-acs-' }
    .sort.map { |key| "#{key}:#{headers[key].strip}\n" }.join
end
canonicalized_resource(uri, query_hash = {}) click to toggle source
# File lib/aliyunsdkcore/roa_client.rb, line 131
def canonicalized_resource(uri, query_hash = {})
  query_string = query_hash.sort.map { |key, value| "#{key}=#{value}" }.join('&')
  query_string.empty? ? uri : "#{uri}?#{query_string}"
end
signature(string_to_sign) click to toggle source
# File lib/aliyunsdkcore/roa_client.rb, line 140
def signature(string_to_sign)
  Base64.encode64(OpenSSL::HMAC.digest('sha1', self.access_key_secret, string_to_sign)).strip
end
string_to_sign(method, uri, headers, query = {}) click to toggle source
# File lib/aliyunsdkcore/roa_client.rb, line 115
def string_to_sign(method, uri, headers, query = {})
  header_string = [
    method,
    headers['accept'],
    headers['content-md5'] || '',
    headers['content-type'] || '',
    headers['date'],
  ].join("\n")
  "#{header_string}\n#{canonicalized_headers(headers)}#{canonicalized_resource(uri, query)}"
end
validate(config) click to toggle source
# File lib/aliyunsdkcore/roa_client.rb, line 144
def validate(config)
  raise ArgumentError, 'must pass "config"' unless config
  raise ArgumentError, 'must pass "config[:endpoint]"' unless config[:endpoint]
  unless config[:endpoint].start_with?('http://') || config[:endpoint].start_with?('https://')
    raise ArgumentError, '"config.endpoint" must starts with \'https://\' or \'http://\'.'
  end
  raise ArgumentError, 'must pass "config[:api_version]"' unless config[:api_version]
  raise ArgumentError, 'must pass "config[:access_key_id]"' unless config[:access_key_id]
  raise ArgumentError, 'must pass "config[:access_key_secret]"' unless config[:access_key_secret]
end