aws-sdk-core 3.39.0 → 3.54.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/lib/aws-sdk-core/async_client_stubs.rb +80 -0
  4. data/lib/aws-sdk-core/binary/decode_handler.rb +9 -1
  5. data/lib/aws-sdk-core/binary/encode_handler.rb +32 -0
  6. data/lib/aws-sdk-core/binary/event_builder.rb +122 -0
  7. data/lib/aws-sdk-core/binary/event_parser.rb +48 -18
  8. data/lib/aws-sdk-core/binary/event_stream_decoder.rb +5 -2
  9. data/lib/aws-sdk-core/binary/event_stream_encoder.rb +53 -0
  10. data/lib/aws-sdk-core/binary.rb +3 -0
  11. data/lib/aws-sdk-core/client_side_monitoring/request_metrics.rb +63 -9
  12. data/lib/aws-sdk-core/client_stubs.rb +1 -1
  13. data/lib/aws-sdk-core/ecs_credentials.rb +12 -8
  14. data/lib/aws-sdk-core/errors.rb +38 -2
  15. data/lib/aws-sdk-core/event_emitter.rb +42 -0
  16. data/lib/aws-sdk-core/instance_profile_credentials.rb +12 -8
  17. data/lib/aws-sdk-core/json/error_handler.rb +19 -2
  18. data/lib/aws-sdk-core/json/handler.rb +19 -1
  19. data/lib/aws-sdk-core/log/param_filter.rb +1 -1
  20. data/lib/aws-sdk-core/param_validator.rb +9 -1
  21. data/lib/aws-sdk-core/plugins/client_metrics_plugin.rb +22 -3
  22. data/lib/aws-sdk-core/plugins/client_metrics_send_plugin.rb +5 -1
  23. data/lib/aws-sdk-core/plugins/event_stream_configuration.rb +14 -0
  24. data/lib/aws-sdk-core/plugins/invocation_id.rb +33 -0
  25. data/lib/aws-sdk-core/plugins/retry_errors.rb +2 -0
  26. data/lib/aws-sdk-core/plugins/stub_responses.rb +19 -7
  27. data/lib/aws-sdk-core/plugins/transfer_encoding.rb +53 -0
  28. data/lib/aws-sdk-core/plugins/user_agent.rb +6 -0
  29. data/lib/aws-sdk-core/process_credentials.rb +7 -1
  30. data/lib/aws-sdk-core/query/handler.rb +6 -1
  31. data/lib/aws-sdk-core/refreshing_credentials.rb +1 -1
  32. data/lib/aws-sdk-core/resources/collection.rb +1 -1
  33. data/lib/aws-sdk-core/structure.rb +6 -2
  34. data/lib/aws-sdk-core/stubbing/protocols/rest.rb +19 -0
  35. data/lib/aws-sdk-core/stubbing/stub_data.rb +13 -4
  36. data/lib/aws-sdk-core/waiters/waiter.rb +2 -2
  37. data/lib/aws-sdk-core/xml/error_handler.rb +26 -3
  38. data/lib/aws-sdk-core.rb +1 -0
  39. data/lib/aws-sdk-sts/client.rb +622 -427
  40. data/lib/aws-sdk-sts/client_api.rb +35 -0
  41. data/lib/aws-sdk-sts/errors.rb +128 -0
  42. data/lib/aws-sdk-sts/types.rb +498 -165
  43. data/lib/aws-sdk-sts.rb +1 -1
  44. data/lib/seahorse/client/async_base.rb +50 -0
  45. data/lib/seahorse/client/async_response.rb +62 -0
  46. data/lib/seahorse/client/base.rb +1 -1
  47. data/lib/seahorse/client/configuration.rb +4 -2
  48. data/lib/seahorse/client/events.rb +1 -1
  49. data/lib/seahorse/client/h2/connection.rb +244 -0
  50. data/lib/seahorse/client/h2/handler.rb +151 -0
  51. data/lib/seahorse/client/http/async_response.rb +42 -0
  52. data/lib/seahorse/client/http/response.rb +13 -8
  53. data/lib/seahorse/client/net_http/patches.rb +7 -1
  54. data/lib/seahorse/client/networking_error.rb +28 -0
  55. data/lib/seahorse/client/plugin.rb +1 -1
  56. data/lib/seahorse/client/plugins/content_length.rb +7 -2
  57. data/lib/seahorse/client/plugins/h2.rb +64 -0
  58. data/lib/seahorse/model/api.rb +4 -0
  59. data/lib/seahorse/model/operation.rb +4 -0
  60. data/lib/seahorse/model/shapes.rb +2 -2
  61. data/lib/seahorse.rb +9 -0
  62. metadata +23 -5
@@ -13,9 +13,12 @@ module Aws
13
13
 
14
14
  # @param [Seahorse::Client::RequestContext] context
15
15
  # @param [String] message
16
- def initialize(context, message)
16
+ # @param [Aws::Structure] data
17
+ def initialize(context, message, data = Aws::EmptyStructure.new)
17
18
  @code = self.class.code
19
+ @message = message if message && !message.empty?
18
20
  @context = context
21
+ @data = data
19
22
  super(message)
20
23
  end
21
24
 
@@ -26,6 +29,9 @@ module Aws
26
29
  # that triggered the remote service to return this error.
27
30
  attr_reader :context
28
31
 
32
+ # @return [Aws::Structure]
33
+ attr_reader :data
34
+
29
35
  class << self
30
36
 
31
37
  # @return [String]
@@ -34,6 +40,24 @@ module Aws
34
40
  end
35
41
  end
36
42
 
43
+ # Raised when InstanceProfileCredentialsProvider or
44
+ # EcsCredentialsProvider fails to parse the metadata response after retries
45
+ class MetadataParserError < RuntimeError
46
+ def initialize(*args)
47
+ msg = "Failed to parse metadata service response."
48
+ super(msg)
49
+ end
50
+ end
51
+
52
+ # Raised when a `streaming` operation has `requiresLength` trait
53
+ # enabled but request payload size/length cannot be calculated
54
+ class MissingContentLength < RuntimeError
55
+ def initialize(*args)
56
+ msg = 'Required `Content-Length` value missing for the request.'
57
+ super(msg)
58
+ end
59
+ end
60
+
37
61
  # Rasied when endpoint discovery failed for operations
38
62
  # that requires endpoints from endpoint discovery
39
63
  class EndpointDiscoveryError < RuntimeError
@@ -58,10 +82,18 @@ module Aws
58
82
 
59
83
  end
60
84
 
85
+ # Raised when attempting to #signal an event before
86
+ # making an async request
87
+ class SignalEventError < RuntimeError; end
88
+
61
89
  # Raised when EventStream Parser failed to parse
62
90
  # a raw event message
63
91
  class EventStreamParserError < RuntimeError; end
64
92
 
93
+ # Raise when EventStream Builder failed to build
94
+ # an event message with parameters provided
95
+ class EventStreamBuilderError < RuntimeError; end
96
+
65
97
  # Error event in an event stream which has event_type :error
66
98
  # error code and error message can be retrieved when available.
67
99
  #
@@ -223,7 +255,11 @@ Known AWS regions include (not specific to this service):
223
255
  def error_class(error_code)
224
256
  constant = error_class_constant(error_code)
225
257
  if error_const_set?(constant)
226
- const_get(constant)
258
+ # modeled error class exist
259
+ # set code attribute
260
+ err_class = const_get(constant)
261
+ err_class.code = constant.to_s
262
+ err_class
227
263
  else
228
264
  set_error_constant(constant)
229
265
  end
@@ -3,8 +3,19 @@ module Aws
3
3
 
4
4
  def initialize
5
5
  @listeners = {}
6
+ @validate_event = true
7
+ @status = :sleep
8
+ @signal_queue = Queue.new
6
9
  end
7
10
 
11
+ attr_accessor :stream
12
+
13
+ attr_accessor :encoder
14
+
15
+ attr_accessor :validate_event
16
+
17
+ attr_accessor :signal_queue
18
+
8
19
  def on(type, callback)
9
20
  (@listeners[type] ||= []) << callback
10
21
  end
@@ -16,5 +27,36 @@ module Aws
16
27
  end
17
28
  end
18
29
 
30
+ def emit(type, params)
31
+ unless @stream
32
+ raise Aws::Errors::SignalEventError.new(
33
+ "Singaling events before making async request"\
34
+ " is not allowed."
35
+ )
36
+ end
37
+ if @validate_event && type != :end_stream
38
+ Aws::ParamValidator.validate!(
39
+ @encoder.rules.shape.member(type), params)
40
+ end
41
+ _ready_for_events?
42
+ @stream.data(
43
+ @encoder.encode(type, params),
44
+ end_stream: type == :end_stream
45
+ )
46
+ end
47
+
48
+ private
49
+
50
+ def _ready_for_events?
51
+ return true if @status == :ready
52
+
53
+ # blocked until once initial 200 response is received
54
+ # signal will be available in @signal_queue
55
+ # and this check will no longer be blocked
56
+ @signal_queue.pop
57
+ @status = :ready
58
+ true
59
+ end
60
+
19
61
  end
20
62
  end
@@ -69,14 +69,18 @@ module Aws
69
69
  # Retry loading credentials up to 3 times is the instance metadata
70
70
  # service is responding but is returning invalid JSON documents
71
71
  # in response to the GET profile credentials call.
72
- retry_errors([JSON::ParserError, StandardError], max_retries: 3) do
73
- c = JSON.parse(get_credentials.to_s)
74
- @credentials = Credentials.new(
75
- c['AccessKeyId'],
76
- c['SecretAccessKey'],
77
- c['Token']
78
- )
79
- @expiration = c['Expiration'] ? Time.iso8601(c['Expiration']) : nil
72
+ begin
73
+ retry_errors([JSON::ParserError, StandardError], max_retries: 3) do
74
+ c = JSON.parse(get_credentials.to_s)
75
+ @credentials = Credentials.new(
76
+ c['AccessKeyId'],
77
+ c['SecretAccessKey'],
78
+ c['Token']
79
+ )
80
+ @expiration = c['Expiration'] ? Time.iso8601(c['Expiration']) : nil
81
+ end
82
+ rescue JSON::ParserError
83
+ raise Aws::Errors::MetadataParserError.new
80
84
  end
81
85
  end
82
86
 
@@ -17,9 +17,10 @@ module Aws
17
17
  json = Json.load(body)
18
18
  code = error_code(json, context)
19
19
  message = error_message(code, json)
20
- [code, message]
20
+ data = parse_error_data(context, code)
21
+ [code, message, data]
21
22
  rescue Json::ParseError
22
- [http_status_error_code(context), '']
23
+ [http_status_error_code(context), '', EmptyStructure.new]
23
24
  end
24
25
 
25
26
  def error_code(json, context)
@@ -41,6 +42,22 @@ module Aws
41
42
  end
42
43
  end
43
44
 
45
+ def parse_error_data(context, code)
46
+ data = EmptyStructure.new
47
+ if error_rules = context.operation.errors
48
+ error_rules.each do |rule|
49
+ # match modeled shape name with the type(code) only
50
+ # some type(code) might contains invalid characters
51
+ # such as ':' (efs) etc
52
+ match = rule.shape.name == code.gsub(/[^^a-zA-Z0-9]/, '')
53
+ if match && rule.shape.members.any?
54
+ data = Parser.new(rule).parse(context.http_response.body_contents)
55
+ end
56
+ end
57
+ end
58
+ data
59
+ end
60
+
44
61
  end
45
62
  end
46
63
  end
@@ -40,7 +40,25 @@ module Aws
40
40
  Json.load(context.http_response.body_contents)
41
41
  elsif rules = context.operation.output
42
42
  json = context.http_response.body_contents
43
- Parser.new(rules).parse(json == '' ? '{}' : json)
43
+ if json.is_a?(Array)
44
+ # an array of emitted events
45
+ if json[0].respond_to?(:response)
46
+ # initial response exists
47
+ # it must be the first event arrived
48
+ resp_struct = json.shift.response
49
+ else
50
+ resp_struct = context.operation.output.shape.struct_class.new
51
+ end
52
+
53
+ rules.shape.members.each do |name, ref|
54
+ if ref.eventstream
55
+ resp_struct.send("#{name}=", json.to_enum)
56
+ end
57
+ end
58
+ resp_struct
59
+ else
60
+ Parser.new(rules).parse(json == '' ? '{}' : json)
61
+ end
44
62
  else
45
63
  EmptyStructure.new
46
64
  end
@@ -11,7 +11,7 @@ module Aws
11
11
  #
12
12
  # @api private
13
13
  # begin
14
- SENSITIVE = [:access_token, :account_name, :account_password, :address, :admin_contact, :artifact_credentials, :auth_code, :authentication_token, :authorization_result, :base_32_string_seed, :body, :bot_configuration, :client_id, :client_secret, :configuration, :copy_source_sse_customer_key, :credentials, :custom_attributes, :db_password, :description, :display_name, :email, :email_address, :email_message, :embed_url, :feedback_token, :first_name, :id, :id_token, :input, :input_text, :key_id, :kms_key_id, :kms_master_key_id, :last_name, :local_console_password, :master_account_email, :master_user_password, :message, :name, :new_password, :notes, :old_password, :owner_information, :parameters, :passphrase, :password, :payload, :plaintext, :previous_password, :primary_email, :private_key, :proposed_password, :public_key, :qr_code_png, :query, :refresh_token, :registrant_contact, :request_attributes, :search_query, :secret_access_key, :secret_binary, :secret_code, :secret_hash, :secret_string, :service_password, :session_attributes, :share_notes, :shared_secret, :slots, :sse_customer_key, :ssekms_key_id, :status_message, :task_parameters, :tech_contact, :temporary_password, :text, :token, :trust_password, :upload_credentials, :upload_url, :user_email, :user_name, :username, :value, :values, :variables, :zip_file]
14
+ SENSITIVE = [:access_token, :account_name, :account_password, :address, :admin_contact, :admin_password, :artifact_credentials, :auth_code, :authentication_token, :authorization_result, :backup_plan_tags, :backup_vault_tags, :base_32_string_seed, :body, :bot_configuration, :bot_email, :cause, :client_id, :client_secret, :configuration, :copy_source_sse_customer_key, :credentials, :current_password, :custom_attributes, :db_password, :default_phone_number, :definition, :description, :display_name, :e164_phone_number, :email, :email_address, :email_message, :embed_url, :error, :feedback_token, :file, :first_name, :id, :id_token, :input, :input_text, :key_id, :key_store_password, :kms_key_id, :kms_master_key_id, :lambda_function_arn, :last_name, :local_console_password, :master_account_email, :master_user_password, :message, :name, :new_password, :next_password, :notes, :old_password, :outbound_events_https_endpoint, :output, :owner_information, :parameters, :passphrase, :password, :payload, :phone_number, :plaintext, :previous_password, :primary_email, :primary_provisioned_number, :private_key, :proposed_password, :public_key, :qr_code_png, :query, :recovery_point_tags, :refresh_token, :registrant_contact, :request_attributes, :search_query, :secret_access_key, :secret_binary, :secret_code, :secret_hash, :secret_string, :secret_to_authenticate_initiator, :secret_to_authenticate_target, :security_token, :service_password, :session_attributes, :share_notes, :shared_secret, :slots, :sse_customer_key, :ssekms_key_id, :status_message, :tag_key_list, :tags, :task_parameters, :tech_contact, :temporary_password, :text, :token, :trust_password, :upload_credentials, :upload_url, :user_email, :user_name, :username, :value, :values, :variables, :zip_file]
15
15
  # end
16
16
 
17
17
  def initialize(options = {})
@@ -22,6 +22,7 @@ module Aws
22
22
  ShapeRef.new(shape: shape)
23
23
  end
24
24
  @validate_required = options[:validate_required] != false
25
+ @input = options[:input].nil? ? true : !!options[:input]
25
26
  end
26
27
 
27
28
  # @param [Hash] params
@@ -39,6 +40,7 @@ module Aws
39
40
  return unless correct_type?(ref, values, errors, context)
40
41
 
41
42
  if ref.eventstream
43
+ # input eventstream is provided from event signals
42
44
  values.each do |value|
43
45
  # each event is structure type
44
46
  case value[:message_type]
@@ -58,7 +60,8 @@ module Aws
58
60
  # ensure required members are present
59
61
  if @validate_required
60
62
  shape.required.each do |member_name|
61
- if values[member_name].nil?
63
+ input_eventstream = ref.shape.member(member_name).eventstream && @input
64
+ if values[member_name].nil? && !input_eventstream
62
65
  param = "#{context}[#{member_name.inspect}]"
63
66
  errors << "missing required parameter #{param}"
64
67
  end
@@ -147,6 +150,11 @@ module Aws
147
150
  end
148
151
 
149
152
  def correct_type?(ref, value, errors, context)
153
+ if ref.eventstream && @input
154
+ errors << "instead of providing value directly for eventstreams at input,"\
155
+ " expected to use #signal events per stream"
156
+ return false
157
+ end
150
158
  case value
151
159
  when Hash then true
152
160
  when ref.shape.struct_class then true
@@ -109,6 +109,10 @@ all generated client side metrics. Defaults to an empty string.
109
109
  context.metadata[:client_metrics] = request_metrics
110
110
  start_time = Aws::Util.monotonic_milliseconds
111
111
  final_error_retryable = false
112
+ final_aws_exception = nil
113
+ final_aws_exception_message = nil
114
+ final_sdk_exception = nil
115
+ final_sdk_exception_message = nil
112
116
  begin
113
117
  @handler.call(context)
114
118
  rescue StandardError => e
@@ -137,14 +141,29 @@ all generated client side metrics. Defaults to an empty string.
137
141
  attempt.sdk_exception = e.class.to_s
138
142
  attempt.sdk_exception_msg = e.message
139
143
  end # Else we don't have an SDK exception and are done.
144
+ final_attempt = request_metrics.api_call_attempts.last
145
+ final_aws_exception = final_attempt.aws_exception
146
+ final_aws_exception_message = final_attempt.aws_exception_msg
147
+ final_sdk_exception = final_attempt.sdk_exception
148
+ final_sdk_exception_message = final_attempt.sdk_exception_msg
140
149
  raise e
141
150
  ensure
142
151
  end_time = Aws::Util.monotonic_milliseconds
143
- request_metrics.api_call.complete(
152
+ complete_opts = {
144
153
  latency: end_time - start_time,
145
154
  attempt_count: context.retries + 1,
146
- final_error_retryable: final_error_retryable
147
- )
155
+ user_agent: context.http_request.headers["user-agent"],
156
+ final_error_retryable: final_error_retryable,
157
+ final_http_status_code: context.http_response.status_code,
158
+ final_aws_exception: final_aws_exception,
159
+ final_aws_exception_message: final_aws_exception_message,
160
+ final_sdk_exception: final_sdk_exception,
161
+ final_sdk_exception_message: final_sdk_exception_message
162
+ }
163
+ if context.metadata[:redirect_region]
164
+ complete_opts[:region] = context.metadata[:redirect_region]
165
+ end
166
+ request_metrics.api_call.complete(complete_opts)
148
167
  # Report the metrics by passing the complete RequestMetrics object
149
168
  if publisher
150
169
  publisher.publish(request_metrics)
@@ -7,7 +7,8 @@ module Aws
7
7
  def add_handlers(handlers, config)
8
8
  if config.client_side_monitoring && config.client_side_monitoring_port
9
9
  # AttemptHandler comes just before we would retry an error.
10
- handlers.add(AttemptHandler, step: :sign, priority: 95)
10
+ # Or before we would follow redirects.
11
+ handlers.add(AttemptHandler, step: :sign, priority: 39)
11
12
  # LatencyHandler is as close to sending as possible.
12
13
  handlers.add(LatencyHandler, step: :sign, priority: 0)
13
14
  end
@@ -45,6 +46,9 @@ module Aws
45
46
  context.metadata[:current_call_attempt] = call_attempt
46
47
 
47
48
  resp = @handler.call(context)
49
+ if context.metadata[:redirect_region]
50
+ call_attempt.region = context.metadata[:redirect_region]
51
+ end
48
52
  headers = context.http_response.headers
49
53
  if headers.include?("x-amz-id-2")
50
54
  call_attempt.x_amz_id_2 = headers["x-amz-id-2"]
@@ -10,6 +10,20 @@ module Aws
10
10
  When an EventStream or Proc object is provided, it will be used as callback for each chunk of event stream response received along the way.
11
11
  DOCS
12
12
 
13
+ option(:input_event_stream_handler,
14
+ default: nil,
15
+ doc_type: 'Proc',
16
+ docstring: <<-DOCS)
17
+ When an EventStream or Proc object is provided, it can be used for sending events for the event stream.
18
+ DOCS
19
+
20
+ option(:output_event_stream_handler,
21
+ default: nil,
22
+ doc_type: 'Proc',
23
+ docstring: <<-DOCS)
24
+ When an EventStream or Proc object is provided, it will be used as callback for each chunk of event stream response received along the way.
25
+ DOCS
26
+
13
27
  end
14
28
 
15
29
  end
@@ -0,0 +1,33 @@
1
+ require 'securerandom'
2
+
3
+ module Aws
4
+ module Plugins
5
+
6
+ # @api private
7
+ class InvocationId < Seahorse::Client::Plugin
8
+
9
+ # @api private
10
+ class Handler < Seahorse::Client::Handler
11
+
12
+ def call(context)
13
+ apply_invocation_id(context)
14
+ @handler.call(context)
15
+ end
16
+
17
+ private
18
+
19
+ def apply_invocation_id(context)
20
+ context.http_request.headers['amz-sdk-invocation-id'] = SecureRandom.uuid
21
+ if context[:input_event_emitter]
22
+ # only used for eventstreaming at input
23
+ context.http_request.headers['x-amz-content-sha256'] = 'STREAMING-AWS4-HMAC-SHA256-EVENTS'
24
+ end
25
+ end
26
+
27
+ end
28
+
29
+ handler(Handler, step: :initialize)
30
+
31
+ end
32
+ end
33
+ end
@@ -78,12 +78,14 @@ A delay randomiser function used by the default backoff function. Some predefine
78
78
  'Throttling', # query services
79
79
  'ThrottlingException', # json services
80
80
  'RequestThrottled', # sqs
81
+ 'RequestThrottledException',
81
82
  'ProvisionedThroughputExceededException', # dynamodb
82
83
  'TransactionInProgressException', # dynamodb
83
84
  'RequestLimitExceeded', # ec2
84
85
  'BandwidthLimitExceeded', # cloud search
85
86
  'LimitExceededException', # kinesis
86
87
  'TooManyRequestsException', # batch
88
+ 'PriorRequestNotComplete', # route53
87
89
  ])
88
90
 
89
91
  CHECKSUM_ERRORS = Set.new([
@@ -45,15 +45,18 @@ requests are made, and retries are disabled.
45
45
  def call(context)
46
46
  stub = context.client.next_stub(context)
47
47
  resp = Seahorse::Client::Response.new(context: context)
48
- apply_stub(stub, resp)
49
- resp
48
+ async_mode = context.client.is_a? Seahorse::Client::AsyncBase
49
+ apply_stub(stub, resp, async_mode)
50
+
51
+ async_mode ? Seahorse::Client::AsyncResponse.new(
52
+ context: context, stream: context[:input_event_stream_handler].event_emitter.stream, sync_queue: Queue.new) : resp
50
53
  end
51
54
 
52
- def apply_stub(stub, response)
55
+ def apply_stub(stub, response, async_mode = false)
53
56
  http_resp = response.context.http_response
54
57
  case
55
58
  when stub[:error] then signal_error(stub[:error], http_resp)
56
- when stub[:http] then signal_http(stub[:http], http_resp)
59
+ when stub[:http] then signal_http(stub[:http], http_resp, async_mode)
57
60
  when stub[:data] then response.data = stub[:data]
58
61
  end
59
62
  end
@@ -67,9 +70,18 @@ requests are made, and retries are disabled.
67
70
  end
68
71
 
69
72
  # @param [Seahorse::Client::Http::Response] stub
70
- # @param [Seahorse::Client::Http::Response] http_resp
71
- def signal_http(stub, http_resp)
72
- http_resp.signal_headers(stub.status_code, stub.headers.to_h)
73
+ # @param [Seahorse::Client::Http::Response | Seahorse::Client::Http::AsyncResponse] http_resp
74
+ # @param [Boolean] async_mode
75
+ def signal_http(stub, http_resp, async_mode = false)
76
+ if async_mode
77
+ h2_headers = stub.headers.to_h.inject([]) do |arr, (k, v)|
78
+ arr << [k, v]
79
+ end
80
+ h2_headers << [":status", stub.status_code]
81
+ http_resp.signal_headers(h2_headers)
82
+ else
83
+ http_resp.signal_headers(stub.status_code, stub.headers.to_h)
84
+ end
73
85
  while chunk = stub.body.read(1024 * 1024)
74
86
  http_resp.signal_data(chunk)
75
87
  end
@@ -0,0 +1,53 @@
1
+ module Aws
2
+ module Plugins
3
+
4
+ # For Streaming Input Operations, when `requiresLength` is enabled
5
+ # checking whether `Content-Length` header can be set,
6
+ # for `v4-unsigned-body` operations, set `Transfer-Encoding` header
7
+ class TransferEncoding < Seahorse::Client::Plugin
8
+
9
+ # @api private
10
+ class Handler < Seahorse::Client::Handler
11
+
12
+ def call(context)
13
+ if streaming?(context.operation.input)
14
+ begin
15
+ context.http_request.body.size
16
+ rescue
17
+ if requires_length?(context.operation.input)
18
+ # if size of the IO is not available but required
19
+ raise Aws::Errors::MissingContentLength.new
20
+ elsif context.operation['authtype'] == "v4-unsigned-body"
21
+ context.http_request.headers['Transfer-Encoding'] = 'chunked'
22
+ end
23
+ end
24
+ end
25
+
26
+ @handler.call(context)
27
+ end
28
+
29
+ private
30
+
31
+ def streaming?(ref)
32
+ if payload = ref[:payload_member]
33
+ payload["streaming"] || # checking ref and shape
34
+ payload.shape["streaming"]
35
+ else
36
+ false
37
+ end
38
+ end
39
+
40
+ def requires_length?(ref)
41
+ payload = ref[:payload_member]
42
+ payload["requiresLength"] || # checking ref and shape
43
+ payload.shape["requiresLength"]
44
+ end
45
+
46
+ end
47
+
48
+ handler(Handler, step: :sign)
49
+
50
+ end
51
+
52
+ end
53
+ end
@@ -14,6 +14,8 @@ module Aws
14
14
  end
15
15
 
16
16
  def set_user_agent(context)
17
+ execution_env = ENV["AWS_EXECUTION_ENV"]
18
+
17
19
  ua = "aws-sdk-ruby3/#{CORE_GEM_VERSION}"
18
20
 
19
21
  begin
@@ -28,6 +30,10 @@ module Aws
28
30
  ua += " #{context[:gem_name]}/#{context[:gem_version]}"
29
31
  end
30
32
 
33
+ if execution_env
34
+ ua += " exec-env/#{execution_env}"
35
+ end
36
+
31
37
  ua += " #{context.config.user_agent_suffix}" if context.config.user_agent_suffix
32
38
 
33
39
  context.http_request.headers['User-Agent'] = ua.strip
@@ -27,6 +27,8 @@ module Aws
27
27
  def initialize(process)
28
28
  @process = process
29
29
  @credentials = credentials_from_process(@process)
30
+
31
+ super
30
32
  end
31
33
 
32
34
  private
@@ -38,7 +40,11 @@ module Aws
38
40
  end
39
41
 
40
42
  if process_status.success?
41
- creds_json = JSON.parse(raw_out)
43
+ begin
44
+ creds_json = JSON.parse(raw_out)
45
+ rescue JSON::ParserError
46
+ raise Errors::InvalidProcessCredentialsPayload.new("Invalid JSON response")
47
+ end
42
48
  payload_version = creds_json['Version']
43
49
  if payload_version == 1
44
50
  _parse_payload_format_v1(creds_json)
@@ -27,7 +27,12 @@ module Aws
27
27
  build_request(context)
28
28
  @handler.call(context).on_success do |response|
29
29
  response.error = nil
30
- response.data = parse_xml(context) || EmptyStructure.new
30
+ parsed = parse_xml(context)
31
+ if parsed.nil? || parsed == EmptyStructure
32
+ response.data = EmptyStructure.new
33
+ else
34
+ response.data = parsed
35
+ end
31
36
  end
32
37
  end
33
38
 
@@ -3,7 +3,7 @@ require 'thread'
3
3
  module Aws
4
4
 
5
5
  # Base class used credential classes that can be refreshed. This
6
- # provides basic refresh logic in a thread-safe manor. Classes mixing in
6
+ # provides basic refresh logic in a thread-safe manner. Classes mixing in
7
7
  # this module are expected to implement a #refresh method that populates
8
8
  # the following instance variables:
9
9
  #
@@ -39,7 +39,7 @@ module Aws
39
39
  if @size
40
40
  @batches[0][index]
41
41
  else
42
- raise "unabled to index into a lazy loaded collection"
42
+ raise "unable to index into a lazy loaded collection"
43
43
  end
44
44
  end
45
45
  deprecated :[]
@@ -29,8 +29,7 @@ module Aws
29
29
  def to_h(obj = self)
30
30
  case obj
31
31
  when Struct
32
- obj.members.each.with_object({}) do |member, hash|
33
- value = obj[member]
32
+ obj.each_pair.with_object({}) do |(member, value), hash|
34
33
  hash[member] = to_hash(value) unless value.nil?
35
34
  end
36
35
  when Hash
@@ -45,6 +44,11 @@ module Aws
45
44
  end
46
45
  alias to_hash to_h
47
46
 
47
+ # Wraps the default #to_s logic with filtering of sensitive parameters.
48
+ def to_s(obj = self)
49
+ Aws::Log::ParamFilter.new.filter(obj).to_s
50
+ end
51
+
48
52
  class << self
49
53
 
50
54
  # @api private
@@ -118,6 +118,25 @@ module Aws
118
118
 
119
119
  def encode_event(opts, rules, event_data, builder)
120
120
  event_ref = rules.shape.member(event_data.delete(:event_type))
121
+ explicit_payload = false
122
+ implicit_payload_members = {}
123
+ event_ref.shape.members.each do |name, ref|
124
+ if ref.eventpayload
125
+ explicit_payload = true
126
+ else
127
+ implicit_payload_members[name] = ref
128
+ end
129
+ end
130
+
131
+ if !explicit_payload && !implicit_payload_members.empty?
132
+ unless implicit_payload_members.size > 1
133
+ m_name, _ = implicit_payload_members.first
134
+ value = {}
135
+ value[m_name] = event_data[m_name]
136
+ opts[:payload] = StringIO.new(builder.new(event_ref).serialize(value))
137
+ end
138
+ end
139
+
121
140
  event_data.each do |k, v|
122
141
  member_ref = event_ref.shape.member(k)
123
142
  if member_ref.eventheader