aws-sdk-core 3.191.0 → 3.199.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +153 -1
- data/VERSION +1 -1
- data/lib/aws-sdk-core/binary/decode_handler.rb +3 -9
- data/lib/aws-sdk-core/binary/encode_handler.rb +1 -1
- data/lib/aws-sdk-core/binary/event_builder.rb +34 -37
- data/lib/aws-sdk-core/binary/event_stream_decoder.rb +1 -0
- data/lib/aws-sdk-core/binary/event_stream_encoder.rb +4 -3
- data/lib/aws-sdk-core/cbor/cbor_engine.rb +19 -0
- data/lib/aws-sdk-core/cbor/decoder.rb +310 -0
- data/lib/aws-sdk-core/cbor/encoder.rb +243 -0
- data/lib/aws-sdk-core/cbor.rb +106 -0
- data/lib/aws-sdk-core/client_stubs.rb +3 -2
- data/lib/aws-sdk-core/credential_provider.rb +1 -1
- data/lib/aws-sdk-core/ec2_metadata.rb +1 -1
- data/lib/aws-sdk-core/ecs_credentials.rb +2 -1
- data/lib/aws-sdk-core/endpoints/matchers.rb +5 -1
- data/lib/aws-sdk-core/error_handler.rb +41 -0
- data/lib/aws-sdk-core/event_emitter.rb +0 -16
- data/lib/aws-sdk-core/instance_profile_credentials.rb +3 -2
- data/lib/aws-sdk-core/json/builder.rb +8 -1
- data/lib/aws-sdk-core/json/error_handler.rb +15 -10
- data/lib/aws-sdk-core/json/handler.rb +5 -6
- data/lib/aws-sdk-core/json/json_engine.rb +3 -1
- data/lib/aws-sdk-core/json/oj_engine.rb +7 -1
- data/lib/aws-sdk-core/json/parser.rb +6 -1
- data/lib/aws-sdk-core/json.rb +43 -14
- data/lib/aws-sdk-core/lru_cache.rb +75 -0
- data/lib/aws-sdk-core/pageable_response.rb +1 -1
- data/lib/aws-sdk-core/param_validator.rb +7 -2
- data/lib/aws-sdk-core/plugins/client_metrics_send_plugin.rb +14 -2
- data/lib/aws-sdk-core/plugins/global_configuration.rb +8 -9
- data/lib/aws-sdk-core/plugins/invocation_id.rb +1 -11
- data/lib/aws-sdk-core/plugins/protocols/api_gateway.rb +3 -1
- data/lib/aws-sdk-core/plugins/protocols/ec2.rb +2 -24
- data/lib/aws-sdk-core/plugins/protocols/json_rpc.rb +6 -8
- data/lib/aws-sdk-core/plugins/protocols/query.rb +4 -2
- data/lib/aws-sdk-core/plugins/protocols/rest_json.rb +3 -15
- data/lib/aws-sdk-core/plugins/protocols/rest_xml.rb +3 -0
- data/lib/aws-sdk-core/plugins/protocols/rpc_v2.rb +17 -0
- data/lib/aws-sdk-core/plugins/request_compression.rb +11 -2
- data/lib/aws-sdk-core/plugins/retry_errors.rb +10 -3
- data/lib/aws-sdk-core/plugins/sign.rb +8 -3
- data/lib/aws-sdk-core/plugins/user_agent.rb +61 -26
- data/lib/aws-sdk-core/process_credentials.rb +45 -27
- data/lib/aws-sdk-core/query/ec2_handler.rb +27 -0
- data/lib/aws-sdk-core/query/ec2_param_builder.rb +5 -7
- data/lib/aws-sdk-core/query/handler.rb +4 -4
- data/lib/aws-sdk-core/query/param_builder.rb +2 -2
- data/lib/aws-sdk-core/query.rb +2 -1
- data/lib/aws-sdk-core/rest/content_type_handler.rb +60 -0
- data/lib/aws-sdk-core/rest/handler.rb +3 -4
- data/lib/aws-sdk-core/rest/request/body.rb +32 -5
- data/lib/aws-sdk-core/rest/request/endpoint.rb +24 -4
- data/lib/aws-sdk-core/rest/request/headers.rb +15 -7
- data/lib/aws-sdk-core/rest/request/querystring_builder.rb +23 -11
- data/lib/aws-sdk-core/rest/response/body.rb +15 -1
- data/lib/aws-sdk-core/rest/response/header_list_parser.rb +79 -0
- data/lib/aws-sdk-core/rest/response/headers.rb +8 -3
- data/lib/aws-sdk-core/rest.rb +1 -0
- data/lib/aws-sdk-core/rpc_v2/builder.rb +62 -0
- data/lib/aws-sdk-core/rpc_v2/content_type_handler.rb +45 -0
- data/lib/aws-sdk-core/rpc_v2/error_handler.rb +84 -0
- data/lib/aws-sdk-core/rpc_v2/handler.rb +74 -0
- data/lib/aws-sdk-core/rpc_v2/parser.rb +90 -0
- data/lib/aws-sdk-core/rpc_v2.rb +6 -0
- data/lib/aws-sdk-core/stubbing/protocols/rpc_v2.rb +41 -0
- data/lib/aws-sdk-core/util.rb +39 -0
- data/lib/aws-sdk-core/waiters/poller.rb +1 -1
- data/lib/aws-sdk-core/xml/builder.rb +17 -9
- data/lib/aws-sdk-core/xml/error_handler.rb +32 -42
- data/lib/aws-sdk-core/xml/parser/frame.rb +4 -20
- data/lib/aws-sdk-core/xml/parser/stack.rb +2 -0
- data/lib/aws-sdk-core/xml/parser.rb +2 -6
- data/lib/aws-sdk-core.rb +7 -2
- data/lib/aws-sdk-sso/client.rb +77 -49
- data/lib/aws-sdk-sso.rb +1 -1
- data/lib/aws-sdk-ssooidc/client.rb +127 -51
- data/lib/aws-sdk-ssooidc/client_api.rb +22 -0
- data/lib/aws-sdk-ssooidc/errors.rb +21 -0
- data/lib/aws-sdk-ssooidc/types.rb +77 -9
- data/lib/aws-sdk-ssooidc.rb +1 -1
- data/lib/aws-sdk-sts/client.rb +77 -49
- data/lib/aws-sdk-sts/client_api.rb +8 -8
- data/lib/aws-sdk-sts.rb +1 -1
- data/lib/seahorse/client/async_base.rb +1 -1
- data/lib/seahorse/client/async_response.rb +19 -0
- data/lib/seahorse/client/base.rb +18 -7
- data/lib/seahorse/client/h2/handler.rb +1 -0
- data/lib/seahorse/client/handler.rb +1 -1
- data/lib/seahorse/client/net_http/connection_pool.rb +3 -9
- data/lib/seahorse/client/plugin.rb +8 -0
- data/lib/seahorse/client/plugins/endpoint.rb +0 -1
- data/lib/seahorse/client/plugins/net_http.rb +48 -16
- data/lib/seahorse/model/shapes.rb +2 -2
- metadata +24 -7
- /data/lib/aws-sdk-core/xml/parser/{engines/libxml.rb → libxml_engine.rb} +0 -0
- /data/lib/aws-sdk-core/xml/parser/{engines/nokogiri.rb → nokogiri_engine.rb} +0 -0
- /data/lib/aws-sdk-core/xml/parser/{engines/oga.rb → oga_engine.rb} +0 -0
- /data/lib/aws-sdk-core/xml/parser/{engines/ox.rb → ox_engine.rb} +0 -0
- /data/lib/aws-sdk-core/xml/parser/{engines/rexml.rb → rexml_engine.rb} +0 -0
|
@@ -4,6 +4,23 @@ module Aws
|
|
|
4
4
|
module Plugins
|
|
5
5
|
# @api private
|
|
6
6
|
class UserAgent < Seahorse::Client::Plugin
|
|
7
|
+
METRICS = Aws::Json.load(<<-METRICS)
|
|
8
|
+
{
|
|
9
|
+
"RESOURCE_MODEL": "A",
|
|
10
|
+
"WAITER": "B",
|
|
11
|
+
"PAGINATOR": "C",
|
|
12
|
+
"RETRY_MODE_LEGACY": "D",
|
|
13
|
+
"RETRY_MODE_STANDARD": "E",
|
|
14
|
+
"RETRY_MODE_ADAPTIVE": "F",
|
|
15
|
+
"S3_TRANSFER": "G",
|
|
16
|
+
"S3_CRYPTO_V1N": "H",
|
|
17
|
+
"S3_CRYPTO_V2": "I",
|
|
18
|
+
"S3_EXPRESS_BUCKET": "J",
|
|
19
|
+
"S3_ACCESS_GRANTS": "K",
|
|
20
|
+
"GZIP_REQUEST_COMPRESSION": "L"
|
|
21
|
+
}
|
|
22
|
+
METRICS
|
|
23
|
+
|
|
7
24
|
# @api private
|
|
8
25
|
option(:user_agent_suffix)
|
|
9
26
|
# @api private
|
|
@@ -14,20 +31,29 @@ module Aws
|
|
|
14
31
|
doc_type: 'String',
|
|
15
32
|
docstring: <<-DOCS) do |cfg|
|
|
16
33
|
A unique and opaque application ID that is appended to the
|
|
17
|
-
User-Agent header as app
|
|
18
|
-
maximum length of 50.
|
|
34
|
+
User-Agent header as app/sdk_ua_app_id. It should have a
|
|
35
|
+
maximum length of 50. This variable is sourced from environment
|
|
36
|
+
variable AWS_SDK_UA_APP_ID or the shared config profile attribute sdk_ua_app_id.
|
|
19
37
|
DOCS
|
|
20
38
|
app_id = ENV['AWS_SDK_UA_APP_ID']
|
|
21
39
|
app_id ||= Aws.shared_config.sdk_ua_app_id(profile: cfg.profile)
|
|
22
40
|
app_id
|
|
23
41
|
end
|
|
24
42
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
43
|
+
# Deprecated - must exist for old service gems
|
|
44
|
+
def self.feature(_feature, &block)
|
|
45
|
+
block.call
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def self.metric(metric, &block)
|
|
49
|
+
Thread.current[:aws_sdk_core_user_agent_metric] ||= []
|
|
50
|
+
Thread.current[:aws_sdk_core_user_agent_metric] << METRICS[metric]
|
|
28
51
|
block.call
|
|
29
52
|
ensure
|
|
30
|
-
Thread.current[:
|
|
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
|
|
31
57
|
end
|
|
32
58
|
|
|
33
59
|
# @api private
|
|
@@ -48,15 +74,24 @@ maximum length of 50.
|
|
|
48
74
|
|
|
49
75
|
def to_s
|
|
50
76
|
ua = "aws-sdk-ruby3/#{CORE_GEM_VERSION}"
|
|
51
|
-
ua += ' ua/2.
|
|
52
|
-
|
|
77
|
+
ua += ' ua/2.1'
|
|
78
|
+
if (api_m = api_metadata)
|
|
79
|
+
ua += " #{api_m}"
|
|
80
|
+
end
|
|
53
81
|
ua += " #{os_metadata}"
|
|
54
82
|
ua += " #{language_metadata}"
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
83
|
+
if (env_m = env_metadata)
|
|
84
|
+
ua += " #{env_m}"
|
|
85
|
+
end
|
|
86
|
+
if (app_id_m = app_id_metadata)
|
|
87
|
+
ua += " #{app_id_m}"
|
|
88
|
+
end
|
|
89
|
+
if (framework_m = framework_metadata)
|
|
90
|
+
ua += " #{framework_m}"
|
|
91
|
+
end
|
|
92
|
+
if (metric_m = metric_metadata)
|
|
93
|
+
ua += " #{metric_m}"
|
|
94
|
+
end
|
|
60
95
|
if @context.config.user_agent_suffix
|
|
61
96
|
ua += " #{@context.config.user_agent_suffix}"
|
|
62
97
|
end
|
|
@@ -92,7 +127,6 @@ maximum length of 50.
|
|
|
92
127
|
local_version = Gem::Platform.local.version
|
|
93
128
|
metadata += "##{local_version}" if local_version
|
|
94
129
|
metadata += " md/#{RbConfig::CONFIG['host_cpu']}"
|
|
95
|
-
metadata
|
|
96
130
|
end
|
|
97
131
|
|
|
98
132
|
# Used to be RUBY_ENGINE/RUBY_VERSION
|
|
@@ -106,11 +140,7 @@ maximum length of 50.
|
|
|
106
140
|
"exec-env/#{execution_env}"
|
|
107
141
|
end
|
|
108
142
|
|
|
109
|
-
def
|
|
110
|
-
"cfg/retry-mode##{@context.config.retry_mode}"
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
def app_id
|
|
143
|
+
def app_id_metadata
|
|
114
144
|
return unless (app_id = @context.config.sdk_ua_app_id)
|
|
115
145
|
|
|
116
146
|
# Sanitize and only allow these characters
|
|
@@ -118,12 +148,6 @@ maximum length of 50.
|
|
|
118
148
|
"app/#{app_id}"
|
|
119
149
|
end
|
|
120
150
|
|
|
121
|
-
def feature_metadata
|
|
122
|
-
return unless Thread.current[:aws_sdk_core_user_agent_feature]
|
|
123
|
-
|
|
124
|
-
Thread.current[:aws_sdk_core_user_agent_feature].join(' ')
|
|
125
|
-
end
|
|
126
|
-
|
|
127
151
|
def framework_metadata
|
|
128
152
|
if (frameworks_cfg = @context.config.user_agent_frameworks).empty?
|
|
129
153
|
return
|
|
@@ -140,10 +164,21 @@ maximum length of 50.
|
|
|
140
164
|
end
|
|
141
165
|
frameworks.map { |n, v| "lib/#{n}##{v}" }.join(' ')
|
|
142
166
|
end
|
|
167
|
+
|
|
168
|
+
def metric_metadata
|
|
169
|
+
return unless Thread.current[:aws_sdk_core_user_agent_metric]
|
|
170
|
+
|
|
171
|
+
metrics = Thread.current[:aws_sdk_core_user_agent_metric].join(',')
|
|
172
|
+
# Metric metadata is limited to 1024 bytes
|
|
173
|
+
return "m/#{metrics}" if metrics.bytesize <= 1024
|
|
174
|
+
|
|
175
|
+
# Removes the last unfinished metric
|
|
176
|
+
"m/#{metrics[0...metrics[0..1024].rindex(',')]}"
|
|
177
|
+
end
|
|
143
178
|
end
|
|
144
179
|
end
|
|
145
180
|
|
|
146
|
-
handler(Handler, priority:
|
|
181
|
+
handler(Handler, step: :sign, priority: 97)
|
|
147
182
|
end
|
|
148
183
|
end
|
|
149
184
|
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
|
|
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,40 +25,49 @@ 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
|
|
23
|
-
#
|
|
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
|
|
37
|
+
@credentials = credentials_from_process
|
|
27
38
|
@async_refresh = false
|
|
28
39
|
|
|
29
40
|
super
|
|
30
41
|
end
|
|
31
42
|
|
|
32
43
|
private
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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)
|
|
@@ -64,11 +79,14 @@ module Aws
|
|
|
64
79
|
|
|
65
80
|
@expiration = creds_json['Expiration'] ? Time.iso8601(creds_json['Expiration']) : nil
|
|
66
81
|
return creds if creds.set?
|
|
67
|
-
|
|
82
|
+
|
|
83
|
+
raise Errors::InvalidProcessCredentialsPayload.new(
|
|
84
|
+
'Invalid payload for JSON credentials version 1'
|
|
85
|
+
)
|
|
68
86
|
end
|
|
69
87
|
|
|
70
88
|
def refresh
|
|
71
|
-
@credentials = credentials_from_process
|
|
89
|
+
@credentials = credentials_from_process
|
|
72
90
|
end
|
|
73
91
|
|
|
74
92
|
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
|
|
@@ -31,13 +31,11 @@ module Aws
|
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
def list(ref, values, prefix)
|
|
34
|
-
if values.empty?
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
format(member_ref, value, "#{prefix}.#{n+1}")
|
|
40
|
-
end
|
|
34
|
+
return if values.empty?
|
|
35
|
+
|
|
36
|
+
member_ref = ref.shape.member
|
|
37
|
+
values.each.with_index do |value, n|
|
|
38
|
+
format(member_ref, value, "#{prefix}.#{n + 1}")
|
|
41
39
|
end
|
|
42
40
|
end
|
|
43
41
|
|
|
@@ -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 |
|
|
31
|
-
|
|
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
|
-
|
|
34
|
+
resp.data = EmptyStructure.new
|
|
35
35
|
else
|
|
36
|
-
|
|
36
|
+
resp.data = parsed
|
|
37
37
|
end
|
|
38
38
|
end
|
|
39
39
|
end
|
|
@@ -36,7 +36,7 @@ module Aws
|
|
|
36
36
|
return
|
|
37
37
|
end
|
|
38
38
|
if flat?(ref)
|
|
39
|
-
if name = query_name(
|
|
39
|
+
if (name = query_name(ref))
|
|
40
40
|
parts = prefix.split('.')
|
|
41
41
|
parts.pop
|
|
42
42
|
parts.push(name)
|
|
@@ -82,7 +82,7 @@ module Aws
|
|
|
82
82
|
end
|
|
83
83
|
|
|
84
84
|
def flat?(ref)
|
|
85
|
-
ref.shape.flattened
|
|
85
|
+
ref[:flattened] || ref.shape.flattened
|
|
86
86
|
end
|
|
87
87
|
|
|
88
88
|
def timestamp(ref, value)
|
data/lib/aws-sdk-core/query.rb
CHANGED
|
@@ -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,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Aws
|
|
4
|
+
module Rest
|
|
5
|
+
# NOTE: headers could be already populated if specified on input shape
|
|
6
|
+
class ContentTypeHandler < Seahorse::Client::Handler
|
|
7
|
+
def call(context)
|
|
8
|
+
if eventstream?(context)
|
|
9
|
+
context.http_request.headers['Content-Type'] ||=
|
|
10
|
+
'application/vnd.amazon.eventstream'
|
|
11
|
+
elsif (payload = context.operation.input[:payload_member])
|
|
12
|
+
case payload.shape
|
|
13
|
+
when Seahorse::Model::Shapes::BlobShape
|
|
14
|
+
context.http_request.headers['Content-Type'] ||=
|
|
15
|
+
'application/octet-stream'
|
|
16
|
+
when Seahorse::Model::Shapes::StringShape
|
|
17
|
+
context.http_request.headers['Content-Type'] ||=
|
|
18
|
+
'text/plain'
|
|
19
|
+
else
|
|
20
|
+
apply_default_content_type(context)
|
|
21
|
+
end
|
|
22
|
+
elsif (body = context.http_request.body) &&
|
|
23
|
+
(!body.respond_to?(:size) || non_empty_body?(body))
|
|
24
|
+
apply_default_content_type(context)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
@handler.call(context)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def non_empty_body?(body)
|
|
33
|
+
body.respond_to?(:size) && body.size.positive?
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def eventstream?(context)
|
|
37
|
+
context.operation.input.shape.members.each do |_, ref|
|
|
38
|
+
return true if ref.eventstream
|
|
39
|
+
end
|
|
40
|
+
false
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# content-type defaults as noted here:
|
|
44
|
+
# rest-json: https://smithy.io/2.0/aws/protocols/aws-restxml-protocol.html#content-type
|
|
45
|
+
# rest-xml: https://smithy.io/2.0/aws/protocols/aws-restxml-protocol.html#content-type
|
|
46
|
+
def apply_default_content_type(context)
|
|
47
|
+
protocol = context.config.api.metadata['protocol']
|
|
48
|
+
case protocol
|
|
49
|
+
when 'rest-json'
|
|
50
|
+
context.http_request.headers['Content-Type'] ||=
|
|
51
|
+
'application/json'
|
|
52
|
+
when 'rest-xml'
|
|
53
|
+
context.http_request.headers['Content-Type'] ||=
|
|
54
|
+
'application/xml'
|
|
55
|
+
else raise "Unsupported protocol #{protocol}"
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -7,10 +7,9 @@ module Aws
|
|
|
7
7
|
|
|
8
8
|
def call(context)
|
|
9
9
|
Rest::Request::Builder.new.apply(context)
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
|
@@ -18,10 +18,13 @@ module Aws
|
|
|
18
18
|
# @param [Hash] params
|
|
19
19
|
def apply(http_req, params)
|
|
20
20
|
body = build_body(params)
|
|
21
|
+
|
|
21
22
|
# for rest-json, ensure we send at least an empty object
|
|
22
23
|
# don't send an empty object for streaming? case.
|
|
23
|
-
if body.nil? &&
|
|
24
|
-
|
|
24
|
+
if body.nil? &&
|
|
25
|
+
json_builder? &&
|
|
26
|
+
modeled_body? &&
|
|
27
|
+
!streaming?
|
|
25
28
|
body = '{}'
|
|
26
29
|
end
|
|
27
30
|
http_req.body = body
|
|
@@ -45,13 +48,29 @@ module Aws
|
|
|
45
48
|
params[@rules[:payload]]
|
|
46
49
|
elsif @rules[:payload]
|
|
47
50
|
params = params[@rules[:payload]]
|
|
48
|
-
|
|
51
|
+
if params
|
|
52
|
+
if xml_builder? &&
|
|
53
|
+
@rules.shape.member?(@rules[:payload_member].location_name)
|
|
54
|
+
# serializing payload member name for rest-xml is as follows:
|
|
55
|
+
# 1. Use the member locationName if the member value doesn't match the member's name (default)
|
|
56
|
+
# 2. Use the value of the locationName on the member's target if present
|
|
57
|
+
# 3. Use the shape name of the member's target
|
|
58
|
+
serialize(@rules[:payload_member], params, location_name: payload_location_name)
|
|
59
|
+
else
|
|
60
|
+
serialize(@rules[:payload_member], params)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
49
63
|
else
|
|
50
64
|
params = body_params(params)
|
|
51
65
|
serialize(@rules, params) unless params.empty?
|
|
52
66
|
end
|
|
53
67
|
end
|
|
54
68
|
|
|
69
|
+
def payload_location_name
|
|
70
|
+
@rules[:payload_member].shape['locationName'] ||
|
|
71
|
+
@rules[:payload_member].shape.name
|
|
72
|
+
end
|
|
73
|
+
|
|
55
74
|
def streaming?
|
|
56
75
|
@rules[:payload] && (
|
|
57
76
|
BlobShape === @rules[:payload_member].shape ||
|
|
@@ -59,8 +78,16 @@ module Aws
|
|
|
59
78
|
)
|
|
60
79
|
end
|
|
61
80
|
|
|
62
|
-
def
|
|
63
|
-
@serializer_class
|
|
81
|
+
def xml_builder?
|
|
82
|
+
@serializer_class == Xml::Builder
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def json_builder?
|
|
86
|
+
@serializer_class == Json::Builder
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def serialize(rules, params, location_name: nil)
|
|
90
|
+
@serializer_class.new(rules, location_name: location_name).serialize(params)
|
|
64
91
|
end
|
|
65
92
|
|
|
66
93
|
def body_params(params)
|
|
@@ -30,7 +30,9 @@ module Aws
|
|
|
30
30
|
private
|
|
31
31
|
|
|
32
32
|
def apply_path_params(uri, params)
|
|
33
|
-
path = uri.path.sub(
|
|
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
|
|
@@ -38,22 +40,40 @@ module Aws
|
|
|
38
40
|
|
|
39
41
|
def param_value_for_placeholder(placeholder, params)
|
|
40
42
|
name = param_name(placeholder)
|
|
41
|
-
|
|
43
|
+
param_shape = @rules.shape.member(name).shape
|
|
44
|
+
value =
|
|
45
|
+
case param_shape
|
|
46
|
+
when Seahorse::Model::Shapes::TimestampShape
|
|
47
|
+
timestamp(param_shape, params[name]).to_s
|
|
48
|
+
else
|
|
49
|
+
params[name].to_s
|
|
50
|
+
end
|
|
51
|
+
|
|
42
52
|
raise ArgumentError, ":#{name} must not be blank" if value.empty?
|
|
43
53
|
|
|
44
54
|
if placeholder.include?('+')
|
|
45
|
-
value.gsub(
|
|
55
|
+
value.gsub(%r{[^/]+}) { |v| escape(v) }
|
|
46
56
|
else
|
|
47
57
|
escape(value)
|
|
48
58
|
end
|
|
49
59
|
end
|
|
50
60
|
|
|
51
61
|
def param_name(placeholder)
|
|
52
|
-
location_name = placeholder.gsub(/[{}+]/,'')
|
|
62
|
+
location_name = placeholder.gsub(/[{}+]/, '')
|
|
53
63
|
param_name, _ = @rules.shape.member_by_location_name(location_name)
|
|
54
64
|
param_name
|
|
55
65
|
end
|
|
56
66
|
|
|
67
|
+
def timestamp(ref, value)
|
|
68
|
+
case ref['timestampFormat']
|
|
69
|
+
when 'unixTimestamp' then value.to_i
|
|
70
|
+
when 'rfc822' then value.utc.httpdate
|
|
71
|
+
else
|
|
72
|
+
# serializing as RFC 3399 date-time is the default
|
|
73
|
+
value.utc.iso8601
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
57
77
|
def apply_querystring_params(uri, params)
|
|
58
78
|
# collect params that are supposed to be part of the query string
|
|
59
79
|
parts = @rules.shape.members.inject([]) do |prts, (member_name, member_ref)|
|
|
@@ -20,7 +20,8 @@ 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?
|
|
23
|
+
next if value.nil? || ((ref.shape).is_a?(StringShape) && value.empty?)
|
|
24
|
+
|
|
24
25
|
case ref.location
|
|
25
26
|
when 'header' then apply_header_value(http_req.headers, ref, value)
|
|
26
27
|
when 'headers' then apply_header_map(http_req.headers, ref, value)
|
|
@@ -49,12 +50,19 @@ module Aws
|
|
|
49
50
|
end
|
|
50
51
|
end
|
|
51
52
|
|
|
52
|
-
def list(headers, ref,
|
|
53
|
-
return if !
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
.
|
|
53
|
+
def list(headers, ref, values)
|
|
54
|
+
return if !values || values.empty?
|
|
55
|
+
|
|
56
|
+
member_ref = ref.shape.member
|
|
57
|
+
values = values.collect do |value|
|
|
58
|
+
case member_ref.shape
|
|
59
|
+
when TimestampShape
|
|
60
|
+
timestamp(member_ref, value).to_s
|
|
61
|
+
else
|
|
62
|
+
Seahorse::Util.escape_header_list_string(value.to_s)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
headers[ref.location_name] = values.compact.join(', ')
|
|
58
66
|
end
|
|
59
67
|
|
|
60
68
|
def apply_header_map(headers, ref, values)
|
|
@@ -30,20 +30,30 @@ module Aws
|
|
|
30
30
|
#
|
|
31
31
|
# @return [String] Returns a built querystring
|
|
32
32
|
def build(params)
|
|
33
|
+
# keys in query maps must NOT override other keys
|
|
34
|
+
query_keys = query_keys(params)
|
|
33
35
|
params.map do |(shape_ref, param_value)|
|
|
34
|
-
build_part(shape_ref, param_value)
|
|
35
|
-
end.join('&')
|
|
36
|
+
build_part(shape_ref, param_value, query_keys)
|
|
37
|
+
end.reject { |p| p.nil? || p.empty? }.join('&')
|
|
36
38
|
end
|
|
37
39
|
|
|
38
40
|
private
|
|
39
41
|
|
|
40
|
-
def
|
|
42
|
+
def query_keys(params)
|
|
43
|
+
keys = Set.new
|
|
44
|
+
params.each do |(shape_ref, _)|
|
|
45
|
+
keys << shape_ref.location_name unless shape_ref.shape.is_a?(MapShape)
|
|
46
|
+
end
|
|
47
|
+
keys
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def build_part(shape_ref, param_value, query_keys)
|
|
41
51
|
case shape_ref.shape
|
|
42
52
|
# supported scalar types
|
|
43
53
|
when *SUPPORTED_TYPES
|
|
44
54
|
"#{shape_ref.location_name}=#{query_value(shape_ref, param_value)}"
|
|
45
55
|
when MapShape
|
|
46
|
-
generate_query_map(shape_ref, param_value)
|
|
56
|
+
generate_query_map(shape_ref, param_value, query_keys)
|
|
47
57
|
when ListShape
|
|
48
58
|
generate_query_list(shape_ref, param_value)
|
|
49
59
|
else
|
|
@@ -80,31 +90,33 @@ module Aws
|
|
|
80
90
|
end
|
|
81
91
|
end
|
|
82
92
|
|
|
83
|
-
def generate_query_map(ref, value)
|
|
93
|
+
def generate_query_map(ref, value, query_keys)
|
|
84
94
|
case ref.shape.value.shape
|
|
85
95
|
when StringShape
|
|
86
|
-
query_map_of_string(value)
|
|
96
|
+
query_map_of_string(value, query_keys)
|
|
87
97
|
when ListShape
|
|
88
|
-
query_map_of_string_list(value)
|
|
98
|
+
query_map_of_string_list(value, query_keys)
|
|
89
99
|
else
|
|
90
100
|
msg = 'Only map of string and string list supported'
|
|
91
101
|
raise NotImplementedError, msg
|
|
92
102
|
end
|
|
93
103
|
end
|
|
94
104
|
|
|
95
|
-
def query_map_of_string(hash)
|
|
105
|
+
def query_map_of_string(hash, query_keys)
|
|
96
106
|
list = []
|
|
97
107
|
hash.each_pair do |key, value|
|
|
98
|
-
|
|
108
|
+
key = escape(key)
|
|
109
|
+
list << "#{key}=#{escape(value)}" unless query_keys.include?(key)
|
|
99
110
|
end
|
|
100
111
|
list
|
|
101
112
|
end
|
|
102
113
|
|
|
103
|
-
def query_map_of_string_list(hash)
|
|
114
|
+
def query_map_of_string_list(hash, query_keys)
|
|
104
115
|
list = []
|
|
105
116
|
hash.each_pair do |key, values|
|
|
117
|
+
key = escape(key)
|
|
106
118
|
values.each do |value|
|
|
107
|
-
list << "#{
|
|
119
|
+
list << "#{key}=#{escape(value)}" unless query_keys.include?(key)
|
|
108
120
|
end
|
|
109
121
|
end
|
|
110
122
|
list
|