Skip to content
Matt Muller edited this page Oct 6, 2021 · 12 revisions

The client class is the public interface used for interacting with the service. The client will have methods for each operation defined by the API. Clients are 1:1 with a Smithy service shape and its public methods are 1:1 with Smithy operation shapes.

Initialization

The initialize method creates a new Client instance and resolves any provided configuration values. A Seahorse::MiddlewareBuilder object is created for the operation’s middleware stack, and it can take additional, optional dynamic middleware for the Client instance.

def initialize(options = {})
  @endpoint = options[:endpoint]
  @middleware = Seahorse::MiddlewareBuilder.new(options[:middleware])
  @log_level = options.fetch(:log_level, :info)
  @logger = options.fetch(:logger, Logger.new($stdout, level: @log_level))
  # retry middleware
  @max_attempts = options.fetch(:max_attempts, 4)
  @max_delay = options.fetch(:max_delay, 8)
  # send middleware
  @http_wire_trace = options.fetch(:http_wire_trace, false)
  @stub_responses = options.fetch(:stub_responses, false)
  # validator middleware
  @validate_input = options.fetch(:validate_input, false)
end

Global Middleware

The client exposes a class method that allows for appending middleware to every instance of Client.

@middleware = Seahorse::MiddlewareBuilder.new

def self.middleware
  @middleware
end

Operation Methods

Each Smithy operation shape maps to one operation method in the Client. These operation methods use a static Middleware stack. The middleware stack handles building the request and returning the response data or an error. Additional, optional middleware can be added dynamically to the operation. Streaming operations take a block, and the Seahorse::HTTP::Response object will take an output stream.

def my_operation(params = {}, options = {}, &block)
  stack = Seahorse::MiddlewareStack.new
  input = Params::MyOperationInput.build(params)
  stack.use(...)
  stack.use(...)
  stack.use(...)
  apply_middleware(stack, options[:middleware])
  resp = stack.run(
    request: Seahorse::HTTP::Request.new(url: options.fetch(:endpoint, @endpoint)),
    response: Seahorse::HTTP::Response.new(body: output_stream(options)),
    context: {
      api_method: :my_operation,
      api_name: 'MyOperation',
      params: params,
      logger: @logger
    }
  )
  raise resp.error if resp.error
  resp.data
end

Operation methods take two positional hash parameters, similar to the V3 Ruby SDK. This was done to preserve some backwards compatibility and eases the migration path for users upgrading. However, generated SDKs also support passing params as the operations input type (eg an instance of Types::Input) allowing users to build input using structured classes.

# normal param usage
client.my_operation(param1: p1, param2: p2)

# overriding client options
client.operation(
  { param1: p1, param2: p2 },
  { middleware: ... }
)