class AWS::Core::Client

@private
Base class for all of the Amazon AWS service clients.

def self.add_client_request_method method_name, options = {}, &block

def self.add_client_request_method method_name, options = {}, &block
  method = ClientRequestMethodBuilder.new(self, method_name, &block)
  if xml_grammar = options[:xml_grammar]
    method.process_response do |resp|
      xml_grammar.parse(resp.http_response.body, :context => resp)
      super(resp)
    end
    method.simulate_response do |resp|
      xml_grammar.simulate(resp)
      super(resp)
    end
  end
  module_eval <<-END
    def #{method_name}(*args, &block)
      options = args.first ? args.first : {}
      client_request(#{method_name.inspect}, options, &block)
    end
  END
end

def self.configure_client

def self.configure_client
  module_eval('module Options; end')
  module_eval('module XML; end')
end

def async_request_with_retries response, http_request, retry_delays = nil

def async_request_with_retries response, http_request, retry_delays = nil
  response.http_response = Http::Response.new
  handle = Object.new
  handle.extend AsyncHandle
  handle.on_complete do |status|
    case status
    when :failure
      response.error = StandardError.new("failed to contact the service")
      response.signal_failure
    when :success
      populate_error(response)
      retry_delays ||= sleep_durations(response)
      if should_retry?(response) and !retry_delays.empty?
        response.rebuild_request
        @http_handler.sleep_with_callback(retry_delays.shift) do
          async_request_with_retries(response, response.http_request, retry_delays)
        end
      else
        response.error ?
          response.signal_failure :
          response.signal_success
      end
    end
  end
  @http_handler.handle_async(http_request, response.http_response, handle)
end

def build_request(name, options, &block)

def build_request(name, options, &block)
  # we dont want to pass the async option to the configure block
  opts = options.dup
  opts.delete(:async)
  http_request = new_request
  # configure the http request
  http_request.host = endpoint
  http_request.proxy_uri = config.proxy_uri
  http_request.use_ssl = config.use_ssl?
  http_request.ssl_verify_peer = config.ssl_verify_peer?
  http_request.ssl_ca_file = config.ssl_ca_file
  send("configure_#{name}_request", http_request, opts, &block)
  http_request.headers["user-agent"] = user_agent_string
  http_request.add_authorization!(signer)
  http_request
end

def client_request name, options, &block

def client_request name, options, &block
  return_or_raise(options) do
    log_client_request(name, options) do
      if config.stub_requests?
        response = stub_for(name)
        response.http_request = build_request(name, options, &block)
        response.request_options = options
        response
      else
        client = self
        response = new_response { client.send(:build_request, name, options, &block) }
        response.request_type = name
        response.request_options = options
        if self.class::CACHEABLE_REQUESTS.include?(name) and
            cache = AWS.response_cache and
            cached_response = cache.cached(response)
          cached_response.cached = true
          cached_response
        else
          # process the http request
          options[:async] ?
          make_async_request(response) :
            make_sync_request(response)
          # process the http response
          response.on_success do
            send("process_#{name}_response", response)
            if cache = AWS.response_cache
              cache.add(response)
            end
          end
          response
        end
      end
    end
  end
end

def endpoint

Returns:
  • (String) - the configured endpoint for this client.
def endpoint
  config.send(:"#{self.class.service_ruby_name}_endpoint")
end

def initialize options = {}


HTTP requests that this client constructs.
is BuiltinHttpHandler. This method is used to perform the
handle(request, response) method; an example
* +:http_handler+ -- Any object that implements a

== Optional

Secret Access Key directly to the client.
these options to provide the AWS Access Key ID and AWS
* +:access_key_id+ and +:secret_access_key+ -- You can use

different process).
example by moving the signature computation into a
more tightly control access to your secret access key (for
AWS::Core::DefaultSigner. This option is useful if you want to
for a given string). An example implementation is
sign(string_to_sign) (to return a signature
(to return the AWS Access Key ID) and to
* +:signer+ -- An object that responds to +access_key_id+

There are two options:
To create a client you must provide access to AWS credentials.

== Required Options

Creates a new low-level client.
def initialize options = {}
  if options[:endpoint]
    options[:"#{self.class.service_ruby_name}_endpoint"] = 
      options.delete(:endpoint)
  end
  options_without_config = options.dup
  @config = options_without_config.delete(:config)
  @config ||= AWS.config
  @config = @config.with(options_without_config)
  @signer = @config.signer
  @http_handler = @config.http_handler
  @stubs = {}
end

def make_async_request response

def make_async_request response
  pauses = async_request_with_retries(response, response.http_request)
  response
end

def make_sync_request response

def make_sync_request response
  retry_server_errors do
    response.http_response = http_response =
      Http::Response.new
    @http_handler.handle(response.http_request, http_response)
    populate_error(response)
    response.signal_success unless response.error
    response
  end
end

def new_request

def new_request
  req = self.class::REQUEST_CLASS.new
  req.http_method = 'POST'
  req.headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8'
  req.add_param 'Timestamp', Time.now.utc.strftime('%Y-%m-%dT%H:%M:%SZ')
  req.add_param 'Version', self.class::API_VERSION
  req
end

def new_response(*args, &block)

def new_response(*args, &block)
  Response.new(*args, &block)
end

def new_stub_for method_name

Other tags:
    Private: -
def new_stub_for method_name
  response = Response.new(Http::Request.new, Http::Response.new)
  response.request_type = method_name
  response.request_options = {}
  send("simulate_#{method_name}_response", response)
  response.signal_success
  response
end

def populate_error response

def populate_error response
  # clear out a previous error
  response.error = nil
  status = response.http_response.status
  code = nil
  code = xml_error_grammar.parse(response.http_response.body).code if
    xml_error_response?(response)
  
  case
  when response.timeout?
    response.error = Timeout::Error.new
  when code
    response.error =
      service_module::Errors.error_class(code).new(response.http_request,
                                                   response.http_response)
  when status >= 500
    response.error =
      Errors::ServerError.new(response.http_request, response.http_response)
  when status >= 300
    response.error =
      Errors::ClientError.new(response.http_request, response.http_response)
  end
end

def retry_server_errors &block

def retry_server_errors &block
  response = yield
  sleeps = sleep_durations(response)
  while should_retry?(response)
    break if sleeps.empty?
    Kernel.sleep(sleeps.shift)
    # rebuild the request to get a fresh signature
    response.rebuild_request
    response = yield
  end
  response
end

def return_or_raise options, &block

def return_or_raise options, &block
  response = yield
  unless options[:async]
    raise response.error if response.error
  end
  response
end

def scaling_factor response

def scaling_factor response
  response.throttled? ? (0.5 + Kernel.rand * 0.1) : 0.3
end

def service_module

def service_module
  AWS.const_get(self.class.to_s[/(\w+)::Client/, 1])
end

def should_retry? response

def should_retry? response
  response.timeout? or
    response.throttled? or
    response.error.kind_of?(Errors::ServerError)
end

def sleep_durations response

def sleep_durations response
  factor = scaling_factor(response)
  Array.new(config.max_retries) {|n| (2 ** n) * factor }
end

def stub_for method_name

Other tags:
    Private: -

Other tags:
    See: new_stub_for -
def stub_for method_name
  @stubs[method_name] ||= new_stub_for(method_name)
end

def user_agent_string

def user_agent_string
  engine = (RUBY_ENGINE rescue nil or "ruby")
  user_agent = "%s aws-sdk-ruby/#{VERSION} %s/%s %s" %
    [config.user_agent_prefix, engine, RUBY_VERSION, RUBY_PLATFORM]
  user_agent.strip!
  if AWS.memoizing?
    user_agent << " memoizing"
  end
  user_agent
end

def with_config config

Returns:
  • (Core::Client) - Returns a new client object with the given

Parameters:
  • The (Configuration) -- configuration object to use.
def with_config config
  self.class.new(:config => config)
end

def with_http_handler(handler = nil, &blk)

Returns:
  • (Core::Client) - Returns a new instance of the client class with

Parameters:
  • handler (nil) -- A new http handler. Leave blank and pass a
def with_http_handler(handler = nil, &blk)
  handler ||= Http::Handler.new(@http_handler, &blk)
  with_options(:http_handler => handler)
end

def with_options options

Other tags:
    See: AWS.config - detailed list of accepted options.

Parameters:
  • options (Hash) --
def with_options options
  with_config(config.with(options))
end

def xml_error_grammar

def xml_error_grammar
  if service_module::const_defined?(:Errors) and
      service_module::Errors::const_defined?(:BASE_ERROR_GRAMMAR)
    service_module::Errors::BASE_ERROR_GRAMMAR
  else
    XmlGrammar
  end
end

def xml_error_response? response

def xml_error_response? response
  response.http_response.status >= 300 and
    response.http_response.body and
    xml_error_grammar.parse(response.http_response.body).respond_to?(:code)
end