Skip to content

Improvements to make V4 work #291

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: decaf
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions gems/smithy-cbor/lib/smithy-cbor/deserializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ def map(shape, values, target = nil)
end

def structure(shape, values, target = nil)
# TODO: iterate shape members instead of values
return Schema::EmptyStructure.new if shape == Prelude::Unit

target = shape.type.new if target.nil?
Expand All @@ -77,6 +78,7 @@ def structure(shape, values, target = nil)
end

def union(shape, values, target = nil)
# TODO: delete target instead of checking key?
key, value = values.flatten
return nil if key.nil? || key == ' __target'

Expand Down
1 change: 1 addition & 0 deletions gems/smithy-client/lib/smithy-client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
require_relative 'smithy-client/plugin'
require_relative 'smithy-client/plugin_list'
require_relative 'smithy-client/retry'
require_relative 'smithy-client/util'
require_relative 'smithy-client/input'
require_relative 'smithy-client/output'
require_relative 'smithy-client/base'
Expand Down
17 changes: 1 addition & 16 deletions gems/smithy-client/lib/smithy-client/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,7 @@ def service
end

# @param [ServiceShape] service
def service=(service)
@service = service
define_operation_methods
end
attr_writer :service

# @option options [ServiceShape] :service (ServiceShape.new)
# @option options [Array<Plugin>] :plugins ([]) A list of plugins to
Expand All @@ -177,18 +174,6 @@ def define(options = {})

private

def define_operation_methods
operations_module = Module.new
@service.operation_names.each do |method_name|
operations_module.send(:define_method, method_name) do |*args, &block|
params = args[0] || {}
options = args[1] || {}
build_input(method_name, params).send_request(options, &block)
end
end
include(operations_module)
end

def build_plugins
plugins.map { |plugin| plugin.is_a?(Class) ? plugin.new : plugin }
end
Expand Down
2 changes: 1 addition & 1 deletion gems/smithy-client/lib/smithy-client/errors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def initialize(context, message, data)
@code = self.class.code
@context = context
@message = extract_message(message, data)
@data = data
@data = data # TODO: delegate to this?
super(@message)
end

Expand Down
51 changes: 51 additions & 0 deletions gems/smithy-client/lib/smithy-client/plugins/checksum_required.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# frozen_string_literal: true

require 'openssl'

module Smithy
module Client
module Plugins
# @api private
class ChecksumRequired < Plugin
def add_handlers(handlers, _config)
# Ensure checksum is computed AFTER the request is built but BEFORE it is signed
handlers.add(Handler, priority: 15)
end

# @api private
class Handler < Client::Handler
CHUNK_SIZE = 1 * 1024 * 1024 # one MB

def call(context)
if checksum_required_operation?(context)
context.request.headers['Content-Md5'] ||= md5(context.request.body)
end
@handler.call(context)
end

private

def checksum_required_operation?(context)
context.operation.traits.include?('smithy.api#httpChecksumRequired')
end

def md5(value)
md5 = OpenSSL::Digest.new('MD5')
update_in_chunks(md5, value)
md5.base64digest
end

def update_in_chunks(digest, io)
loop do
chunk = io.read(CHUNK_SIZE)
break unless chunk

digest.update(chunk)
end
io.rewind
end
end
end
end
end
end
69 changes: 69 additions & 0 deletions gems/smithy-client/lib/smithy-client/plugins/host_prefix.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# frozen_string_literal: true

module Smithy
module Client
module Plugins
# @api private
class HostPrefix < Plugin
option(
:disable_host_prefix_injection,
default: false,
doc_type: 'Boolean',
docstring: 'When true, the SDK will not prepend the modeled host prefix to the endpoint.'
) do |_config|
value = ENV['DISABLE_HOST_PREFIX_INJECTION'] || 'false'
Util.str_to_bool(value)
end

def after_initialize(client)
validate_disable_host_prefix_injection(client.config)
end

def validate_disable_host_prefix_injection(config)
return if [true, false].include?(config.disable_host_prefix_injection)

raise ArgumentError,
':disable_host_prefix_injection must be either `true` or `false`'
end

def add_handlers(handlers, config)
handlers.add(Handler, priority: 25) unless config.disable_host_prefix_injection
end

# @api private
class Handler < Smithy::Client::Handler
def call(context)
host_prefix = context.operation.traits.dig('smithy.api#endpoint', 'hostPrefix')
apply_host_prefix(context, host_prefix) if host_prefix
@handler.call(context)
end

private

# TODO: optimize this to collect all labels in one pass
def apply_host_prefix(context, host_prefix)
input = context.operation.input
prefix = host_prefix.gsub(/\{.+?}/) do |label|
label_value(input, label.delete('{}'), context.params)
end
context.request.endpoint.host = prefix + context.request.endpoint.host
end

def label_value(input, label, params)
name = nil
input.members.each do |member_name, member_shape|
next unless member_shape.traits.include?('smithy.api#hostLabel')
next unless member_shape.name == label

name = member_name
end
raise ArgumentError, "#{label} is not a valid host label" if name.nil?
raise ArgumentError, "params[#{name}] must not be nil or blank" if params[name].nil? || params[name].empty?

params[name]
end
end
end
end
end
end
34 changes: 34 additions & 0 deletions gems/smithy-client/lib/smithy-client/plugins/idempotency_token.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# frozen_string_literal: true

require 'securerandom'

module Smithy
module Client
module Plugins
# @api private
class IdempotencyToken < Plugin
def add_handlers(handlers, _config)
handlers.add(Handler, step: :initialize)
end

# @api private
class Handler < Client::Handler
def call(context)
apply_idempotency_token(context.operation.input, context.params)
@handler.call(context)
end

private

def apply_idempotency_token(input, params)
input.members.each do |member_name, member_shape|
next unless member_shape.traits.include?('smithy.api#idempotencyToken')

params[member_name] ||= SecureRandom.uuid
end
end
end
end
end
end
end
Loading