Skip to content

Commit 439a5cb

Browse files
committed
Improvements to make V4 work
1 parent ec0341b commit 439a5cb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+1033
-169
lines changed

gems/smithy-cbor/lib/smithy-cbor/deserializer.rb

+2
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ def map(shape, values, target = nil)
6363
end
6464

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

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

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

gems/smithy-client/lib/smithy-client.rb

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
require_relative 'smithy-client/plugin'
2525
require_relative 'smithy-client/plugin_list'
2626
require_relative 'smithy-client/retry'
27+
require_relative 'smithy-client/util'
2728
require_relative 'smithy-client/input'
2829
require_relative 'smithy-client/output'
2930
require_relative 'smithy-client/base'

gems/smithy-client/lib/smithy-client/base.rb

+1-16
Original file line numberDiff line numberDiff line change
@@ -156,10 +156,7 @@ def service
156156
end
157157

158158
# @param [ServiceShape] service
159-
def service=(service)
160-
@service = service
161-
define_operation_methods
162-
end
159+
attr_writer :service
163160

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

178175
private
179176

180-
def define_operation_methods
181-
operations_module = Module.new
182-
@service.operation_names.each do |method_name|
183-
operations_module.send(:define_method, method_name) do |*args, &block|
184-
params = args[0] || {}
185-
options = args[1] || {}
186-
build_input(method_name, params).send_request(options, &block)
187-
end
188-
end
189-
include(operations_module)
190-
end
191-
192177
def build_plugins
193178
plugins.map { |plugin| plugin.is_a?(Class) ? plugin.new : plugin }
194179
end

gems/smithy-client/lib/smithy-client/errors.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def initialize(context, message, data)
2929
@code = self.class.code
3030
@context = context
3131
@message = extract_message(message, data)
32-
@data = data
32+
@data = data # TODO: delegate to this?
3333
super(@message)
3434
end
3535

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# frozen_string_literal: true
2+
3+
require 'openssl'
4+
5+
module Smithy
6+
module Client
7+
module Plugins
8+
# @api private
9+
class ChecksumRequired < Plugin
10+
def add_handlers(handlers, _config)
11+
# Ensure checksum is computed AFTER the request is built but BEFORE it is signed
12+
handlers.add(Handler, priority: 15)
13+
end
14+
15+
# @api private
16+
class Handler < Client::Handler
17+
CHUNK_SIZE = 1 * 1024 * 1024 # one MB
18+
19+
def call(context)
20+
if checksum_required_operation?(context)
21+
context.request.headers['Content-Md5'] ||= md5(context.request.body)
22+
end
23+
@handler.call(context)
24+
end
25+
26+
private
27+
28+
def checksum_required_operation?(context)
29+
context.operation.traits.include?('smithy.api#httpChecksumRequired')
30+
end
31+
32+
def md5(value)
33+
md5 = OpenSSL::Digest.new('MD5')
34+
update_in_chunks(md5, value)
35+
md5.base64digest
36+
end
37+
38+
def update_in_chunks(digest, io)
39+
loop do
40+
chunk = io.read(CHUNK_SIZE)
41+
break unless chunk
42+
43+
digest.update(chunk)
44+
end
45+
io.rewind
46+
end
47+
end
48+
end
49+
end
50+
end
51+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# frozen_string_literal: true
2+
3+
module Smithy
4+
module Client
5+
module Plugins
6+
# @api private
7+
class HostPrefix < Plugin
8+
option(
9+
:disable_host_prefix_injection,
10+
default: false,
11+
doc_type: 'Boolean',
12+
docstring: 'When true, the SDK will not prepend the modeled host prefix to the endpoint.'
13+
) do |_config|
14+
value = ENV['DISABLE_HOST_PREFIX_INJECTION'] || 'false'
15+
Util.str_to_bool(value)
16+
end
17+
18+
def after_initialize(client)
19+
validate_disable_host_prefix_injection(client.config)
20+
end
21+
22+
def validate_disable_host_prefix_injection(config)
23+
return if [true, false].include?(config.disable_host_prefix_injection)
24+
25+
raise ArgumentError,
26+
':disable_host_prefix_injection must be either `true` or `false`'
27+
end
28+
29+
def add_handlers(handlers, config)
30+
handlers.add(Handler, priority: 25) unless config.disable_host_prefix_injection
31+
end
32+
33+
# @api private
34+
class Handler < Smithy::Client::Handler
35+
def call(context)
36+
host_prefix = context.operation.traits.dig('smithy.api#endpoint', 'hostPrefix')
37+
apply_host_prefix(context, host_prefix) if host_prefix
38+
@handler.call(context)
39+
end
40+
41+
private
42+
43+
# TODO: optimize this to collect all labels in one pass
44+
def apply_host_prefix(context, host_prefix)
45+
input = context.operation.input
46+
prefix = host_prefix.gsub(/\{.+?}/) do |label|
47+
label_value(input, label.delete('{}'), context.params)
48+
end
49+
context.request.endpoint.host = prefix + context.request.endpoint.host
50+
end
51+
52+
def label_value(input, label, params)
53+
name = nil
54+
input.members.each do |member_name, member_shape|
55+
next unless member_shape.traits.include?('smithy.api#hostLabel')
56+
next unless member_shape.name == label
57+
58+
name = member_name
59+
end
60+
raise ArgumentError, "#{label} is not a valid host label" if name.nil?
61+
raise ArgumentError, "params[#{name}] must not be nil or blank" if params[name].nil? || params[name].empty?
62+
63+
params[name]
64+
end
65+
end
66+
end
67+
end
68+
end
69+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# frozen_string_literal: true
2+
3+
require 'securerandom'
4+
5+
module Smithy
6+
module Client
7+
module Plugins
8+
# @api private
9+
class IdempotencyToken < Plugin
10+
def add_handlers(handlers, _config)
11+
handlers.add(Handler, step: :initialize)
12+
end
13+
14+
# @api private
15+
class Handler < Client::Handler
16+
def call(context)
17+
apply_idempotency_token(context.operation.input, context.params)
18+
@handler.call(context)
19+
end
20+
21+
private
22+
23+
def apply_idempotency_token(input, params)
24+
input.members.each do |member_name, member_shape|
25+
next unless member_shape.traits.include?('smithy.api#idempotencyToken')
26+
27+
params[member_name] ||= SecureRandom.uuid
28+
end
29+
end
30+
end
31+
end
32+
end
33+
end
34+
end

0 commit comments

Comments
 (0)