aws-sdk-core 3.197.0 → 3.220.0

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 (139) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +297 -0
  3. data/VERSION +1 -1
  4. data/lib/aws-defaults/default_configuration.rb +1 -2
  5. data/lib/aws-defaults.rb +4 -1
  6. data/lib/aws-sdk-core/arn.rb +1 -3
  7. data/lib/aws-sdk-core/assume_role_credentials.rb +12 -5
  8. data/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +13 -7
  9. data/lib/aws-sdk-core/binary/decode_handler.rb +3 -4
  10. data/lib/aws-sdk-core/binary/encode_handler.rb +1 -1
  11. data/lib/aws-sdk-core/binary/event_stream_decoder.rb +1 -0
  12. data/lib/aws-sdk-core/binary/event_stream_encoder.rb +4 -3
  13. data/lib/aws-sdk-core/cbor/decoder.rb +308 -0
  14. data/lib/aws-sdk-core/cbor/encoder.rb +243 -0
  15. data/lib/aws-sdk-core/cbor.rb +53 -0
  16. data/lib/aws-sdk-core/client_side_monitoring.rb +9 -0
  17. data/lib/aws-sdk-core/client_stubs.rb +8 -7
  18. data/lib/aws-sdk-core/credential_provider_chain.rb +13 -6
  19. data/lib/aws-sdk-core/credentials.rb +13 -6
  20. data/lib/aws-sdk-core/endpoints/endpoint.rb +3 -1
  21. data/lib/aws-sdk-core/endpoints/matchers.rb +6 -9
  22. data/lib/aws-sdk-core/endpoints.rb +74 -18
  23. data/lib/aws-sdk-core/error_handler.rb +41 -0
  24. data/lib/aws-sdk-core/errors.rb +9 -0
  25. data/lib/aws-sdk-core/json/error_handler.rb +8 -9
  26. data/lib/aws-sdk-core/json/handler.rb +6 -6
  27. data/lib/aws-sdk-core/json/json_engine.rb +3 -1
  28. data/lib/aws-sdk-core/json/oj_engine.rb +7 -1
  29. data/lib/aws-sdk-core/json/parser.rb +2 -0
  30. data/lib/aws-sdk-core/json.rb +43 -14
  31. data/lib/aws-sdk-core/log/param_filter.rb +2 -2
  32. data/lib/aws-sdk-core/log/param_formatter.rb +7 -3
  33. data/lib/aws-sdk-core/log.rb +10 -0
  34. data/lib/aws-sdk-core/param_validator.rb +1 -1
  35. data/lib/aws-sdk-core/plugins/bearer_authorization.rb +2 -0
  36. data/lib/aws-sdk-core/plugins/checksum_algorithm.rb +332 -169
  37. data/lib/aws-sdk-core/plugins/credentials_configuration.rb +7 -3
  38. data/lib/aws-sdk-core/plugins/global_configuration.rb +8 -9
  39. data/lib/aws-sdk-core/plugins/http_checksum.rb +2 -8
  40. data/lib/aws-sdk-core/plugins/protocols/api_gateway.rb +3 -1
  41. data/lib/aws-sdk-core/plugins/protocols/ec2.rb +2 -24
  42. data/lib/aws-sdk-core/plugins/protocols/json_rpc.rb +6 -8
  43. data/lib/aws-sdk-core/plugins/protocols/query.rb +4 -2
  44. data/lib/aws-sdk-core/plugins/protocols/rest_json.rb +4 -3
  45. data/lib/aws-sdk-core/plugins/protocols/rest_xml.rb +5 -1
  46. data/lib/aws-sdk-core/plugins/protocols/rpc_v2.rb +17 -0
  47. data/lib/aws-sdk-core/plugins/regional_endpoint.rb +74 -25
  48. data/lib/aws-sdk-core/plugins/retry_errors.rb +0 -1
  49. data/lib/aws-sdk-core/plugins/sign.rb +13 -11
  50. data/lib/aws-sdk-core/plugins/signature_v2.rb +2 -1
  51. data/lib/aws-sdk-core/plugins/signature_v4.rb +2 -1
  52. data/lib/aws-sdk-core/plugins/stub_responses.rb +29 -2
  53. data/lib/aws-sdk-core/plugins/telemetry.rb +75 -0
  54. data/lib/aws-sdk-core/plugins/transfer_encoding.rb +16 -9
  55. data/lib/aws-sdk-core/plugins/user_agent.rb +26 -8
  56. data/lib/aws-sdk-core/plugins.rb +39 -0
  57. data/lib/aws-sdk-core/process_credentials.rb +47 -28
  58. data/lib/aws-sdk-core/query/ec2_handler.rb +27 -0
  59. data/lib/aws-sdk-core/query/handler.rb +4 -4
  60. data/lib/aws-sdk-core/query.rb +2 -1
  61. data/lib/aws-sdk-core/resources.rb +8 -0
  62. data/lib/aws-sdk-core/rest/{request/content_type.rb → content_type_handler.rb} +1 -1
  63. data/lib/aws-sdk-core/rest/handler.rb +3 -4
  64. data/lib/aws-sdk-core/rest/request/endpoint.rb +3 -1
  65. data/lib/aws-sdk-core/rest/request/headers.rb +2 -2
  66. data/lib/aws-sdk-core/rest.rb +1 -1
  67. data/lib/aws-sdk-core/rpc_v2/builder.rb +62 -0
  68. data/lib/aws-sdk-core/rpc_v2/cbor_engine.rb +18 -0
  69. data/lib/aws-sdk-core/rpc_v2/content_type_handler.rb +47 -0
  70. data/lib/aws-sdk-core/rpc_v2/error_handler.rb +85 -0
  71. data/lib/aws-sdk-core/rpc_v2/handler.rb +79 -0
  72. data/lib/aws-sdk-core/rpc_v2/parser.rb +90 -0
  73. data/lib/aws-sdk-core/rpc_v2.rb +69 -0
  74. data/lib/aws-sdk-core/shared_config.rb +7 -2
  75. data/lib/aws-sdk-core/shared_credentials.rb +0 -7
  76. data/lib/aws-sdk-core/sso_credentials.rb +2 -1
  77. data/lib/aws-sdk-core/stubbing/protocols/ec2.rb +12 -11
  78. data/lib/aws-sdk-core/stubbing/protocols/json.rb +11 -10
  79. data/lib/aws-sdk-core/stubbing/protocols/query.rb +7 -6
  80. data/lib/aws-sdk-core/stubbing/protocols/rest.rb +2 -1
  81. data/lib/aws-sdk-core/stubbing/protocols/rest_json.rb +9 -8
  82. data/lib/aws-sdk-core/stubbing/protocols/rest_xml.rb +6 -5
  83. data/lib/aws-sdk-core/stubbing/protocols/rpc_v2.rb +39 -0
  84. data/lib/aws-sdk-core/stubbing.rb +22 -0
  85. data/lib/aws-sdk-core/telemetry/base.rb +177 -0
  86. data/lib/aws-sdk-core/telemetry/no_op.rb +70 -0
  87. data/lib/aws-sdk-core/telemetry/otel.rb +235 -0
  88. data/lib/aws-sdk-core/telemetry/span_kind.rb +22 -0
  89. data/lib/aws-sdk-core/telemetry/span_status.rb +59 -0
  90. data/lib/aws-sdk-core/telemetry.rb +78 -0
  91. data/lib/aws-sdk-core/waiters/poller.rb +9 -4
  92. data/lib/aws-sdk-core/xml/error_handler.rb +11 -37
  93. data/lib/aws-sdk-core/xml/parser.rb +2 -6
  94. data/lib/aws-sdk-core.rb +82 -108
  95. data/lib/aws-sdk-sso/client.rb +99 -37
  96. data/lib/aws-sdk-sso/client_api.rb +7 -0
  97. data/lib/aws-sdk-sso/endpoint_parameters.rb +9 -6
  98. data/lib/aws-sdk-sso/endpoint_provider.rb +14 -18
  99. data/lib/aws-sdk-sso/endpoints.rb +2 -54
  100. data/lib/aws-sdk-sso/plugins/endpoints.rb +19 -20
  101. data/lib/aws-sdk-sso/types.rb +1 -0
  102. data/lib/aws-sdk-sso.rb +15 -11
  103. data/lib/aws-sdk-ssooidc/client.rb +123 -55
  104. data/lib/aws-sdk-ssooidc/client_api.rb +5 -0
  105. data/lib/aws-sdk-ssooidc/endpoint_parameters.rb +9 -6
  106. data/lib/aws-sdk-ssooidc/endpoint_provider.rb +14 -18
  107. data/lib/aws-sdk-ssooidc/endpoints.rb +2 -54
  108. data/lib/aws-sdk-ssooidc/plugins/endpoints.rb +19 -20
  109. data/lib/aws-sdk-ssooidc/types.rb +21 -15
  110. data/lib/aws-sdk-ssooidc.rb +15 -11
  111. data/lib/aws-sdk-sts/client.rb +307 -89
  112. data/lib/aws-sdk-sts/client_api.rb +28 -2
  113. data/lib/aws-sdk-sts/customizations.rb +5 -1
  114. data/lib/aws-sdk-sts/endpoint_parameters.rb +10 -9
  115. data/lib/aws-sdk-sts/endpoint_provider.rb +33 -38
  116. data/lib/aws-sdk-sts/endpoints.rb +2 -118
  117. data/lib/aws-sdk-sts/errors.rb +16 -0
  118. data/lib/aws-sdk-sts/plugins/endpoints.rb +19 -28
  119. data/lib/aws-sdk-sts/types.rb +171 -28
  120. data/lib/aws-sdk-sts.rb +15 -11
  121. data/lib/seahorse/client/base.rb +17 -7
  122. data/lib/seahorse/client/h2/handler.rb +13 -3
  123. data/lib/seahorse/client/handler.rb +1 -1
  124. data/lib/seahorse/client/net_http/connection_pool.rb +10 -2
  125. data/lib/seahorse/client/net_http/handler.rb +21 -9
  126. data/lib/seahorse/client/plugins/endpoint.rb +0 -1
  127. data/lib/seahorse/client/plugins/net_http.rb +9 -0
  128. data/lib/seahorse/client/request_context.rb +8 -1
  129. data/lib/seahorse/client/response.rb +2 -0
  130. data/sig/aws-sdk-core/telemetry/base.rbs +46 -0
  131. data/sig/aws-sdk-core/telemetry/otel.rbs +22 -0
  132. data/sig/aws-sdk-core/telemetry/span_kind.rbs +15 -0
  133. data/sig/aws-sdk-core/telemetry/span_status.rbs +24 -0
  134. metadata +62 -18
  135. /data/lib/aws-sdk-core/xml/parser/{engines/libxml.rb → libxml_engine.rb} +0 -0
  136. /data/lib/aws-sdk-core/xml/parser/{engines/nokogiri.rb → nokogiri_engine.rb} +0 -0
  137. /data/lib/aws-sdk-core/xml/parser/{engines/oga.rb → oga_engine.rb} +0 -0
  138. /data/lib/aws-sdk-core/xml/parser/{engines/ox.rb → ox_engine.rb} +0 -0
  139. /data/lib/aws-sdk-core/xml/parser/{engines/rexml.rb → rexml_engine.rb} +0 -0
@@ -17,7 +17,24 @@ module Aws
17
17
  "S3_CRYPTO_V2": "I",
18
18
  "S3_EXPRESS_BUCKET": "J",
19
19
  "S3_ACCESS_GRANTS": "K",
20
- "GZIP_REQUEST_COMPRESSION": "L"
20
+ "GZIP_REQUEST_COMPRESSION": "L",
21
+ "PROTOCOL_RPC_V2_CBOR": "M",
22
+ "ENDPOINT_OVERRIDE": "N",
23
+ "ACCOUNT_ID_ENDPOINT": "O",
24
+ "ACCOUNT_ID_MODE_PREFERRED": "P",
25
+ "ACCOUNT_ID_MODE_DISABLED": "Q",
26
+ "ACCOUNT_ID_MODE_REQUIRED": "R",
27
+ "SIGV4A_SIGNING": "S",
28
+ "RESOLVED_ACCOUNT_ID": "T",
29
+ "FLEXIBLE_CHECKSUMS_REQ_CRC32" : "U",
30
+ "FLEXIBLE_CHECKSUMS_REQ_CRC32C" : "V",
31
+ "FLEXIBLE_CHECKSUMS_REQ_CRC64" : "W",
32
+ "FLEXIBLE_CHECKSUMS_REQ_SHA1" : "X",
33
+ "FLEXIBLE_CHECKSUMS_REQ_SHA256" : "Y",
34
+ "FLEXIBLE_CHECKSUMS_REQ_WHEN_SUPPORTED" : "Z",
35
+ "FLEXIBLE_CHECKSUMS_REQ_WHEN_REQUIRED" : "a",
36
+ "FLEXIBLE_CHECKSUMS_RES_WHEN_SUPPORTED" : "b",
37
+ "FLEXIBLE_CHECKSUMS_RES_WHEN_REQUIRED" : "c"
21
38
  }
22
39
  METRICS
23
40
 
@@ -45,15 +62,13 @@ variable AWS_SDK_UA_APP_ID or the shared config profile attribute sdk_ua_app_id.
45
62
  block.call
46
63
  end
47
64
 
48
- def self.metric(metric, &block)
65
+ def self.metric(*metrics, &block)
49
66
  Thread.current[:aws_sdk_core_user_agent_metric] ||= []
50
- Thread.current[:aws_sdk_core_user_agent_metric] << METRICS[metric]
67
+ metrics = metrics.map { |metric| METRICS[metric] }.compact
68
+ Thread.current[:aws_sdk_core_user_agent_metric].concat(metrics)
51
69
  block.call
52
70
  ensure
53
- Thread.current[:aws_sdk_core_user_agent_metric].pop
54
- if Thread.current[:aws_sdk_core_user_agent_metric].empty?
55
- Thread.current[:aws_sdk_core_user_agent_metric] = nil
56
- end
71
+ Thread.current[:aws_sdk_core_user_agent_metric].pop(metrics.size)
57
72
  end
58
73
 
59
74
  # @api private
@@ -166,7 +181,10 @@ variable AWS_SDK_UA_APP_ID or the shared config profile attribute sdk_ua_app_id.
166
181
  end
167
182
 
168
183
  def metric_metadata
169
- return unless Thread.current[:aws_sdk_core_user_agent_metric]
184
+ if Thread.current[:aws_sdk_core_user_agent_metric].nil? ||
185
+ Thread.current[:aws_sdk_core_user_agent_metric].empty?
186
+ return
187
+ end
170
188
 
171
189
  metrics = Thread.current[:aws_sdk_core_user_agent_metric].join(',')
172
190
  # Metric metadata is limited to 1024 bytes
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ # setup autoloading for Plugins
5
+ # Most plugins are required explicitly from service clients
6
+ # but users may reference them outside of client usage.
7
+ module Plugins
8
+ autoload :ApiKey, 'aws-sdk-core/plugins/api_key'
9
+ autoload :BearerAuthorization, 'aws-sdk-core/plugins/bearer_authorization'
10
+ autoload :ChecksumAlgorithm, 'aws-sdk-core/plugins/checksum_algorithm'
11
+ autoload :ClientMetricsPlugin, 'aws-sdk-core/plugins/client_metrics_plugin'
12
+ autoload :ClientMetricsSendPlugin, 'aws-sdk-core/plugins/client_metrics_send_plugin'
13
+ autoload :CredentialsConfiguration, 'aws-sdk-core/plugins/credentials_configuration'
14
+ autoload :DefaultsMode, 'aws-sdk-core/plugins/defaults_mode'
15
+ autoload :EndpointDiscovery, 'aws-sdk-core/plugins/endpoint_discovery'
16
+ autoload :EndpointPattern, 'aws-sdk-core/plugins/endpoint_pattern'
17
+ autoload :EventStreamConfiguration, 'aws-sdk-core/plugins/event_stream_configuration'
18
+ autoload :GlobalConfiguration, 'aws-sdk-core/plugins/global_configuration'
19
+ autoload :HelpfulSocketErrors, 'aws-sdk-core/plugins/helpful_socket_errors'
20
+ autoload :HttpChecksum, 'aws-sdk-core/plugins/http_checksum'
21
+ autoload :IdempotencyToken, 'aws-sdk-core/plugins/idempotency_token'
22
+ autoload :InvocationId, 'aws-sdk-core/plugins/invocation_id'
23
+ autoload :JsonvalueConverter, 'aws-sdk-core/plugins/jsonvalue_converter'
24
+ autoload :Logging, 'aws-sdk-core/plugins/logging'
25
+ autoload :ParamConverter, 'aws-sdk-core/plugins/param_converter'
26
+ autoload :ParamValidator, 'aws-sdk-core/plugins/param_validator'
27
+ autoload :RecursionDetection, 'aws-sdk-core/plugins/recursion_detection'
28
+ autoload :RegionalEndpoint, 'aws-sdk-core/plugins/regional_endpoint'
29
+ autoload :RequestCompression, 'aws-sdk-core/plugins/request_compression'
30
+ autoload :ResponsePaging, 'aws-sdk-core/plugins/response_paging'
31
+ autoload :RetryErrors, 'aws-sdk-core/plugins/retry_errors'
32
+ autoload :Sign, 'aws-sdk-core/plugins/sign'
33
+ autoload :SignatureV4, 'aws-sdk-core/plugins/signature_v4'
34
+ autoload :StubResponses, 'aws-sdk-core/plugins/stub_responses'
35
+ autoload :Telemetry, 'aws-sdk-core/plugins/telemetry'
36
+ autoload :TransferEncoding, 'aws-sdk-core/plugins/transfer_encoding'
37
+ autoload :UserAgent, 'aws-sdk-core/plugins/user_agent'
38
+ end
39
+ end
@@ -2,9 +2,15 @@
2
2
 
3
3
  module Aws
4
4
  # A credential provider that executes a given process and attempts
5
- # to read its stdout to recieve a JSON payload containing the credentials.
5
+ # to read its stdout to receive a JSON payload containing the credentials.
6
6
  #
7
- # credentials = Aws::ProcessCredentials.new('/usr/bin/credential_proc')
7
+ # credentials = Aws::ProcessCredentials.new(['/usr/bin/credential_proc'])
8
+ # ec2 = Aws::EC2::Client.new(credentials: credentials)
9
+ #
10
+ # Arguments should be provided as strings in the array, for example:
11
+ #
12
+ # process = ['/usr/bin/credential_proc', 'arg1', 'arg2']
13
+ # credentials = Aws::ProcessCredentials.new(process)
8
14
  # ec2 = Aws::EC2::Client.new(credentials: credentials)
9
15
  #
10
16
  # Automatically handles refreshing credentials if an Expiration time is
@@ -19,56 +25,69 @@ module Aws
19
25
  # Creates a new ProcessCredentials object, which allows an
20
26
  # external process to be used as a credential provider.
21
27
  #
22
- # @param [String] process Invocation string for process
23
- # credentials provider.
28
+ # @param [Array<String>, String] process An array of strings including
29
+ # the process name and its arguments to execute, or a single string to be
30
+ # executed by the shell (deprecated and insecure).
24
31
  def initialize(process)
32
+ if process.is_a?(String)
33
+ warn('Passing a single string to Aws::ProcessCredentials.new '\
34
+ 'is insecure, please use use an array of system arguments instead')
35
+ end
25
36
  @process = process
26
- @credentials = credentials_from_process(@process)
37
+ @credentials = credentials_from_process
27
38
  @async_refresh = false
28
39
 
29
40
  super
30
41
  end
31
42
 
32
43
  private
33
- def credentials_from_process(proc_invocation)
34
- begin
35
- raw_out = `#{proc_invocation}`
36
- process_status = $?
37
- rescue Errno::ENOENT
38
- raise Errors::InvalidProcessCredentialsPayload.new("Could not find process #{proc_invocation}")
44
+
45
+ def credentials_from_process
46
+ r, w = IO.pipe
47
+ success = system(*@process, out: w)
48
+ w.close
49
+ raw_out = r.read
50
+ r.close
51
+
52
+ unless success
53
+ raise Errors::InvalidProcessCredentialsPayload.new(
54
+ 'credential_process provider failure, the credential process had '\
55
+ 'non zero exit status and failed to provide credentials'
56
+ )
39
57
  end
40
58
 
41
- if process_status.success?
42
- begin
43
- creds_json = Aws::Json.load(raw_out)
44
- rescue Aws::Json::ParseError
45
- raise Errors::InvalidProcessCredentialsPayload.new("Invalid JSON response")
46
- end
47
- payload_version = creds_json['Version']
48
- if payload_version == 1
49
- _parse_payload_format_v1(creds_json)
50
- else
51
- raise Errors::InvalidProcessCredentialsPayload.new("Invalid version #{payload_version} for credentials payload")
52
- end
53
- else
54
- raise Errors::InvalidProcessCredentialsPayload.new('credential_process provider failure, the credential process had non zero exit status and failed to provide credentials')
59
+ begin
60
+ creds_json = Aws::Json.load(raw_out)
61
+ rescue Aws::Json::ParseError
62
+ raise Errors::InvalidProcessCredentialsPayload.new('Invalid JSON response')
55
63
  end
64
+
65
+ payload_version = creds_json['Version']
66
+ return _parse_payload_format_v1(creds_json) if payload_version == 1
67
+
68
+ raise Errors::InvalidProcessCredentialsPayload.new(
69
+ "Invalid version #{payload_version} for credentials payload"
70
+ )
56
71
  end
57
72
 
58
73
  def _parse_payload_format_v1(creds_json)
59
74
  creds = Credentials.new(
60
75
  creds_json['AccessKeyId'],
61
76
  creds_json['SecretAccessKey'],
62
- creds_json['SessionToken']
77
+ creds_json['SessionToken'],
78
+ account_id: creds_json['AccountId']
63
79
  )
64
80
 
65
81
  @expiration = creds_json['Expiration'] ? Time.iso8601(creds_json['Expiration']) : nil
66
82
  return creds if creds.set?
67
- raise Errors::InvalidProcessCredentialsPayload.new("Invalid payload for JSON credentials version 1")
83
+
84
+ raise Errors::InvalidProcessCredentialsPayload.new(
85
+ 'Invalid payload for JSON credentials version 1'
86
+ )
68
87
  end
69
88
 
70
89
  def refresh
71
- @credentials = credentials_from_process(@process)
90
+ @credentials = credentials_from_process
72
91
  end
73
92
 
74
93
  def near_expiration?(expiration_length)
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ # @api private
5
+ module Query
6
+ class EC2Handler < Aws::Query::Handler
7
+
8
+ def apply_params(param_list, params, rules)
9
+ Aws::Query::EC2ParamBuilder.new(param_list).apply(rules, params)
10
+ end
11
+
12
+ def parse_xml(context)
13
+ if (rules = context.operation.output)
14
+ parser = Xml::Parser.new(rules)
15
+ parser.parse(xml(context)) do |path, value|
16
+ if path.size == 2 && path.last == 'requestId'
17
+ context.metadata[:request_id] = value
18
+ end
19
+ end
20
+ else
21
+ EmptyStructure.new
22
+ end
23
+ end
24
+
25
+ end
26
+ end
27
+ end
@@ -27,13 +27,13 @@ module Aws
27
27
  # @return [Seahorse::Client::Response]
28
28
  def call(context)
29
29
  build_request(context)
30
- @handler.call(context).on_success do |response|
31
- response.error = nil
30
+ @handler.call(context).on_success do |resp|
31
+ resp.error = nil
32
32
  parsed = parse_xml(context)
33
33
  if parsed.nil? || parsed == EmptyStructure
34
- response.data = EmptyStructure.new
34
+ resp.data = EmptyStructure.new
35
35
  else
36
- response.data = parsed
36
+ resp.data = parsed
37
37
  end
38
38
  end
39
39
  end
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'query/ec2_param_builder'
4
3
  require_relative 'query/handler'
4
+ require_relative 'query/ec2_handler'
5
5
  require_relative 'query/param'
6
6
  require_relative 'query/param_builder'
7
+ require_relative 'query/ec2_param_builder'
7
8
  require_relative 'query/param_list'
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ # setup autoloading for Resources module
5
+ module Resources
6
+ autoload :Collection, 'aws-sdk-core/resources/collection'
7
+ end
8
+ end
@@ -35,7 +35,7 @@ module Aws
35
35
 
36
36
  def eventstream?(context)
37
37
  context.operation.input.shape.members.each do |_, ref|
38
- return ref if ref.eventstream
38
+ return true if ref.eventstream
39
39
  end
40
40
  false
41
41
  end
@@ -7,10 +7,9 @@ module Aws
7
7
 
8
8
  def call(context)
9
9
  Rest::Request::Builder.new.apply(context)
10
- resp = @handler.call(context)
11
- resp.on(200..299) { |response| Response::Parser.new.apply(response) }
12
- resp.on(200..599) { |response| apply_request_id(context) }
13
- resp
10
+ response = @handler.call(context)
11
+ response.on(200..299) { |resp| Response::Parser.new.apply(resp) }
12
+ response.on(200..599) { |_resp| apply_request_id(context) }
14
13
  end
15
14
 
16
15
  private
@@ -30,7 +30,9 @@ module Aws
30
30
  private
31
31
 
32
32
  def apply_path_params(uri, params)
33
- path = uri.path.sub(%r{/$}, '') + @path_pattern.split('?')[0]
33
+ path = uri.path.sub(%r{/$}, '')
34
+ # handle trailing slash
35
+ path += @path_pattern.split('?')[0] if path.empty? || @path_pattern != '/'
34
36
  uri.path = path.gsub(/{.+?}/) do |placeholder|
35
37
  param_value_for_placeholder(placeholder, params)
36
38
  end
@@ -20,7 +20,7 @@ module Aws
20
20
  def apply(http_req, params)
21
21
  @rules.shape.members.each do |name, ref|
22
22
  value = params[name]
23
- next if value.nil? || ((ref.shape).is_a?(StringShape) && value.empty?)
23
+ next if value.nil?
24
24
 
25
25
  case ref.location
26
26
  when 'header' then apply_header_value(http_req.headers, ref, value)
@@ -51,7 +51,7 @@ module Aws
51
51
  end
52
52
 
53
53
  def list(headers, ref, values)
54
- return if !values || values.empty?
54
+ return if values.nil?
55
55
 
56
56
  member_ref = ref.shape.member
57
57
  values = values.collect do |value|
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'rest/handler'
4
+ require_relative 'rest/content_type_handler'
4
5
  require_relative 'rest/request/body'
5
6
  require_relative 'rest/request/builder'
6
7
  require_relative 'rest/request/endpoint'
7
8
  require_relative 'rest/request/headers'
8
9
  require_relative 'rest/request/querystring_builder'
9
- require_relative 'rest/request/content_type'
10
10
  require_relative 'rest/response/body'
11
11
  require_relative 'rest/response/headers'
12
12
  require_relative 'rest/response/parser'
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'base64'
4
+
5
+ module Aws
6
+ module RpcV2
7
+ class Builder
8
+ include Seahorse::Model::Shapes
9
+
10
+ def initialize(rules, _options = {})
11
+ @rules = rules
12
+ end
13
+
14
+ def serialize(params)
15
+ # If the input shape is empty, do not set a body. This is
16
+ # different than if the input shape is a structure with no members.
17
+ return nil if @rules.shape.struct_class == EmptyStructure
18
+
19
+ RpcV2.encode(format(@rules, params))
20
+ end
21
+
22
+ private
23
+
24
+ def structure(ref, values)
25
+ shape = ref.shape
26
+ values.each_pair.with_object({}) do |(key, value), data|
27
+ if shape.member?(key) && !value.nil?
28
+ member_ref = shape.member(key)
29
+ member_name = member_ref.location_name || key
30
+ data[member_name] = format(member_ref, value)
31
+ end
32
+ end
33
+ end
34
+
35
+ def list(ref, values)
36
+ member_ref = ref.shape.member
37
+ values.collect { |value| format(member_ref, value) }
38
+ end
39
+
40
+ def map(ref, values)
41
+ value_ref = ref.shape.value
42
+ values.each.with_object({}) do |(key, value), data|
43
+ data[key] = format(value_ref, value)
44
+ end
45
+ end
46
+
47
+ def blob(value)
48
+ (String === value ? value : value.read).force_encoding(Encoding::BINARY)
49
+ end
50
+
51
+ def format(ref, value)
52
+ case ref.shape
53
+ when StructureShape then structure(ref, value)
54
+ when ListShape then list(ref, value)
55
+ when MapShape then map(ref, value)
56
+ when BlobShape then blob(value)
57
+ else value
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../cbor'
4
+
5
+ module Aws
6
+ module RpcV2
7
+ # Pure Ruby implementation of CBOR encode and decode
8
+ module CborEngine
9
+ def self.encode(data)
10
+ Cbor::Encoder.new.add(data).bytes
11
+ end
12
+
13
+ def self.decode(bytes)
14
+ Cbor::Decoder.new(bytes.force_encoding(Encoding::BINARY)).decode
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ module RpcV2
5
+ class ContentTypeHandler < Seahorse::Client::Handler
6
+ def call(context)
7
+ content_type =
8
+ if eventstream_input?(context)
9
+ 'application/vnd.amazon.eventstream'
10
+ elsif !empty_input_structure?(context)
11
+ 'application/cbor'
12
+ end
13
+ accept =
14
+ if eventstream_output?(context)
15
+ 'application/vnd.amazon.eventstream'
16
+ else
17
+ 'application/cbor'
18
+ end
19
+
20
+ headers = context.http_request.headers
21
+ headers['Content-Type'] ||= content_type if content_type
22
+ headers['Accept'] ||= accept
23
+ @handler.call(context)
24
+ end
25
+
26
+ private
27
+
28
+ def eventstream_input?(context)
29
+ context.operation.input.shape.members.each do |_, ref|
30
+ return true if ref.eventstream
31
+ end
32
+ false
33
+ end
34
+
35
+ def eventstream_output?(context)
36
+ context.operation.output.shape.members.each do |_, ref|
37
+ return true if ref.eventstream
38
+ end
39
+ false
40
+ end
41
+
42
+ def empty_input_structure?(context)
43
+ context.operation.input.shape.struct_class == EmptyStructure
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ module RpcV2
5
+ class ErrorHandler < Aws::ErrorHandler
6
+
7
+ def call(context)
8
+ # Malformed responses should throw an http based error, so we check
9
+ # 200 range for error handling only for this case.
10
+ @handler.call(context).on(200..599) do |response|
11
+ if !valid_response?(context)
12
+ code, message, data = http_status_error(context)
13
+ response.error = build_error(context, code, message, data)
14
+ elsif (300..599).cover?(context.http_response.status_code)
15
+ response.error = error(context)
16
+ end
17
+ response.data = nil
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def valid_response?(context)
24
+ req_header = context.http_request.headers['smithy-protocol']
25
+ resp_header = context.http_response.headers['smithy-protocol']
26
+ req_header == resp_header
27
+ end
28
+
29
+ def extract_error(body, context)
30
+ data = RpcV2.decode(body)
31
+ code = error_code(data, context)
32
+ message = data['message']
33
+ data = parse_error_data(context, body, code)
34
+ [code, message, data]
35
+ rescue Cbor::Error
36
+ [http_status_error_code(context), '', EmptyStructure.new]
37
+ end
38
+
39
+ def error_code(data, context)
40
+ code =
41
+ if aws_query_error?(context)
42
+ query_header = context.http_response.headers['x-amzn-query-error']
43
+ error, _type = query_header.split(';') # type not supported
44
+ remove_prefix(error, context)
45
+ else
46
+ data['__type']
47
+ end
48
+ if code
49
+ code.split('#').last
50
+ else
51
+ http_status_error_code(context)
52
+ end
53
+ end
54
+
55
+ def parse_error_data(context, body, code)
56
+ data = EmptyStructure.new
57
+ if (error_rules = context.operation.errors)
58
+ error_rules.each do |rule|
59
+ # match modeled shape name with the type(code) only
60
+ # some type(code) might contains invalid characters
61
+ # such as ':' (efs) etc
62
+ match = rule.shape.name == code.gsub(/[^^a-zA-Z0-9]/, '')
63
+ next unless match && rule.shape.members.any?
64
+
65
+ data = Parser.new(rule).parse(body)
66
+ end
67
+ end
68
+ data
69
+ end
70
+
71
+ def aws_query_error?(context)
72
+ context.config.api.metadata['awsQueryCompatible'] &&
73
+ context.http_response.headers['x-amzn-query-error']
74
+ end
75
+
76
+ def remove_prefix(error_code, context)
77
+ if (prefix = context.config.api.metadata['errorPrefix'])
78
+ error_code.sub(/^#{prefix}/, '')
79
+ else
80
+ error_code
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ module RpcV2
5
+ class Handler < Seahorse::Client::Handler
6
+ # @param [Seahorse::Client::RequestContext] context
7
+ # @return [Seahorse::Client::Response]
8
+ def call(context)
9
+ build_request(context)
10
+ response = with_metric { @handler.call(context) }
11
+ response.on(200..299) { |resp| resp.data = parse_body(context) }
12
+ response.on(200..599) { |_resp| apply_request_id(context) }
13
+ response
14
+ end
15
+
16
+ private
17
+
18
+ def with_metric(&block)
19
+ Aws::Plugins::UserAgent.metric('PROTOCOL_RPC_V2_CBOR', &block)
20
+ end
21
+
22
+ def build_request(context)
23
+ context.http_request.headers['Smithy-Protocol'] = 'rpc-v2-cbor'
24
+ context.http_request.headers['X-Amzn-Query-Mode'] = 'true' if query_compatible?(context)
25
+ context.http_request.http_method = 'POST'
26
+ context.http_request.body = build_body(context)
27
+ build_url(context)
28
+ end
29
+
30
+ def build_url(context)
31
+ base = context.http_request.endpoint
32
+ service_name = context.config.api.metadata['targetPrefix']
33
+ base.path += "/service/#{service_name}/operation/#{context.operation.name}"
34
+ end
35
+
36
+ def build_body(context)
37
+ Builder.new(context.operation.input).serialize(context.params)
38
+ end
39
+
40
+ def parse_body(context)
41
+ cbor = context.http_response.body_contents
42
+ if (rules = context.operation.output)
43
+ if cbor.is_a?(Array)
44
+ # an array of emitted events
45
+ if cbor[0].respond_to?(:response)
46
+ # initial response exists
47
+ # it must be the first event arrived
48
+ resp_struct = cbor.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}=", cbor.to_enum)
56
+ end
57
+ end
58
+ resp_struct
59
+ else
60
+ Parser.new(
61
+ rules,
62
+ query_compatible: query_compatible?(context)
63
+ ).parse(cbor)
64
+ end
65
+ else
66
+ EmptyStructure.new
67
+ end
68
+ end
69
+
70
+ def apply_request_id(context)
71
+ context[:request_id] = context.http_response.headers['x-amzn-requestid']
72
+ end
73
+
74
+ def query_compatible?(context)
75
+ context.config.api.metadata.key?('awsQueryCompatible')
76
+ end
77
+ end
78
+ end
79
+ end