aws-sdk-core 3.171.0 → 3.186.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 +155 -0
- data/VERSION +1 -1
- data/lib/aws-defaults/default_configuration.rb +4 -4
- data/lib/aws-sdk-core/credential_provider.rb +3 -0
- data/lib/aws-sdk-core/endpoints/matchers.rb +13 -9
- data/lib/aws-sdk-core/endpoints.rb +5 -1
- data/lib/aws-sdk-core/errors.rb +1 -1
- data/lib/aws-sdk-core/ini_parser.rb +7 -0
- data/lib/aws-sdk-core/instance_profile_credentials.rb +52 -30
- data/lib/aws-sdk-core/json/error_handler.rb +15 -5
- data/lib/aws-sdk-core/json/parser.rb +1 -1
- data/lib/aws-sdk-core/log/formatter.rb +6 -0
- data/lib/aws-sdk-core/pageable_response.rb +3 -1
- data/lib/aws-sdk-core/param_validator.rb +2 -2
- data/lib/aws-sdk-core/plugins/checksum_algorithm.rb +1 -1
- data/lib/aws-sdk-core/plugins/regional_endpoint.rb +109 -33
- data/lib/aws-sdk-core/plugins/request_compression.rb +217 -0
- data/lib/aws-sdk-core/plugins/sign.rb +1 -0
- data/lib/aws-sdk-core/plugins/user_agent.rb +117 -14
- data/lib/aws-sdk-core/refreshing_credentials.rb +0 -6
- data/lib/aws-sdk-core/rest/request/querystring_builder.rb +43 -29
- data/lib/aws-sdk-core/shared_config.rb +47 -18
- data/lib/aws-sdk-core/sso_credentials.rb +1 -1
- data/lib/aws-sdk-core/stubbing/stub_data.rb +11 -0
- data/lib/aws-sdk-core/waiters/poller.rb +3 -1
- data/lib/aws-sdk-sso/client.rb +21 -1
- data/lib/aws-sdk-sso/endpoint_provider.rb +30 -24
- data/lib/aws-sdk-sso/endpoints.rb +1 -0
- data/lib/aws-sdk-sso.rb +1 -1
- data/lib/aws-sdk-ssooidc/client.rb +21 -1
- data/lib/aws-sdk-ssooidc/endpoint_provider.rb +30 -24
- data/lib/aws-sdk-ssooidc/endpoints.rb +1 -0
- data/lib/aws-sdk-ssooidc.rb +1 -1
- data/lib/aws-sdk-sts/client.rb +138 -112
- data/lib/aws-sdk-sts/client_api.rb +12 -1
- data/lib/aws-sdk-sts/endpoint_provider.rb +81 -78
- data/lib/aws-sdk-sts/endpoints.rb +1 -0
- data/lib/aws-sdk-sts/types.rb +35 -11
- data/lib/aws-sdk-sts.rb +1 -1
- data/lib/seahorse/client/configuration.rb +0 -4
- data/lib/seahorse/client/plugins/request_callback.rb +31 -0
- data/lib/seahorse/client/response.rb +6 -0
- data/lib/seahorse/model/operation.rb +3 -0
- metadata +3 -2
@@ -47,44 +47,21 @@ is set to `true`.
|
|
47
47
|
# Legacy endpoints must continue to be generated at client time.
|
48
48
|
option(:regional_endpoint, false)
|
49
49
|
|
50
|
-
|
51
|
-
|
52
|
-
|
50
|
+
option(:ignore_configured_endpoint_urls,
|
51
|
+
doc_type: 'Boolean',
|
52
|
+
docstring: <<-DOCS) do |cfg|
|
53
|
+
Setting to true disables use of endpoint URLs provided via environment
|
54
|
+
variables and the shared configuration file.
|
55
|
+
DOCS
|
56
|
+
resolve_ignore_configured_endpoint_urls(cfg)
|
57
|
+
end
|
58
|
+
|
53
59
|
option(:endpoint, doc_type: String, docstring: <<-DOCS) do |cfg|
|
54
60
|
The client endpoint is normally constructed from the `:region`
|
55
61
|
option. You should only configure an `:endpoint` when connecting
|
56
62
|
to test or custom endpoints. This should be a valid HTTP(S) URI.
|
57
63
|
DOCS
|
58
|
-
|
59
|
-
if cfg.region && endpoint_prefix
|
60
|
-
if cfg.respond_to?(:sts_regional_endpoints)
|
61
|
-
sts_regional = cfg.sts_regional_endpoints
|
62
|
-
end
|
63
|
-
|
64
|
-
# check region is a valid RFC host label
|
65
|
-
unless Seahorse::Util.host_label?(cfg.region)
|
66
|
-
raise Errors::InvalidRegionError
|
67
|
-
end
|
68
|
-
|
69
|
-
region = cfg.region
|
70
|
-
new_region = region.gsub('fips-', '').gsub('-fips', '')
|
71
|
-
if region != new_region
|
72
|
-
warn("Legacy region #{region} was transformed to #{new_region}."\
|
73
|
-
'`use_fips_endpoint` config was set to true.')
|
74
|
-
cfg.override_config(:use_fips_endpoint, true)
|
75
|
-
cfg.override_config(:region, new_region)
|
76
|
-
end
|
77
|
-
|
78
|
-
Aws::Partitions::EndpointProvider.resolve(
|
79
|
-
cfg.region,
|
80
|
-
endpoint_prefix,
|
81
|
-
sts_regional,
|
82
|
-
{
|
83
|
-
dualstack: cfg.use_dualstack_endpoint,
|
84
|
-
fips: cfg.use_fips_endpoint
|
85
|
-
}
|
86
|
-
)
|
87
|
-
end
|
64
|
+
resolve_endpoint(cfg)
|
88
65
|
end
|
89
66
|
|
90
67
|
def after_initialize(client)
|
@@ -117,6 +94,105 @@ to test or custom endpoints. This should be a valid HTTP(S) URI.
|
|
117
94
|
value ||= Aws.shared_config.use_fips_endpoint(profile: cfg.profile)
|
118
95
|
Aws::Util.str_2_bool(value) || false
|
119
96
|
end
|
97
|
+
|
98
|
+
def resolve_ignore_configured_endpoint_urls(cfg)
|
99
|
+
value = ENV['AWS_IGNORE_CONFIGURED_ENDPOINT_URLS']
|
100
|
+
value ||= Aws.shared_config.ignore_configured_endpoint_urls(profile: cfg.profile)
|
101
|
+
Aws::Util.str_2_bool(value&.downcase) || false
|
102
|
+
end
|
103
|
+
|
104
|
+
# NOTE: with Endpoints 2.0, some of this logic is deprecated
|
105
|
+
# but because new old service gems may depend on new core versions
|
106
|
+
# we must preserve that behavior.
|
107
|
+
# Additional behavior controls the setting of the custom SDK::Endpoint
|
108
|
+
# parameter.
|
109
|
+
# When the `regional_endpoint` config is set to true - this indicates to
|
110
|
+
# Endpoints2.0 that a custom endpoint has NOT been configured by the user.
|
111
|
+
def resolve_endpoint(cfg)
|
112
|
+
endpoint = resolve_custom_config_endpoint(cfg)
|
113
|
+
endpoint_prefix = cfg.api.metadata['endpointPrefix']
|
114
|
+
|
115
|
+
return endpoint unless endpoint.nil? && cfg.region && endpoint_prefix
|
116
|
+
|
117
|
+
validate_region!(cfg.region)
|
118
|
+
handle_legacy_pseudo_regions(cfg)
|
119
|
+
|
120
|
+
# set regional_endpoint flag - this indicates to Endpoints 2.0
|
121
|
+
# that a custom endpoint has NOT been configured by the user
|
122
|
+
cfg.override_config(:regional_endpoint, true)
|
123
|
+
|
124
|
+
resolve_legacy_endpoint(cfg)
|
125
|
+
end
|
126
|
+
|
127
|
+
# get a custom configured endpoint from ENV or configuration
|
128
|
+
def resolve_custom_config_endpoint(cfg)
|
129
|
+
return if cfg.ignore_configured_endpoint_urls
|
130
|
+
|
131
|
+
|
132
|
+
env_service_endpoint(cfg) || env_global_endpoint(cfg) || shared_config_endpoint(cfg)
|
133
|
+
end
|
134
|
+
|
135
|
+
def env_service_endpoint(cfg)
|
136
|
+
service_id = cfg.api.metadata['serviceId'] || cfg.api.metadata['endpointPrefix']
|
137
|
+
env_service_id = service_id.gsub(" ", "_").upcase
|
138
|
+
return unless endpoint = ENV["AWS_ENDPOINT_URL_#{env_service_id}"]
|
139
|
+
|
140
|
+
cfg.logger&.debug(
|
141
|
+
"Endpoint configured from ENV['AWS_ENDPOINT_URL_#{env_service_id}']: #{endpoint}\n")
|
142
|
+
endpoint
|
143
|
+
end
|
144
|
+
|
145
|
+
def env_global_endpoint(cfg)
|
146
|
+
return unless endpoint = ENV['AWS_ENDPOINT_URL']
|
147
|
+
|
148
|
+
cfg.logger&.debug(
|
149
|
+
"Endpoint configured from ENV['AWS_ENDPOINT_URL']: #{endpoint}\n")
|
150
|
+
endpoint
|
151
|
+
end
|
152
|
+
|
153
|
+
def shared_config_endpoint(cfg)
|
154
|
+
service_id = cfg.api.metadata['serviceId'] || cfg.api.metadata['endpointPrefix']
|
155
|
+
return unless endpoint = Aws.shared_config.configured_endpoint(profile: cfg.profile, service_id: service_id)
|
156
|
+
|
157
|
+
cfg.logger&.debug(
|
158
|
+
"Endpoint configured from shared config(profile: #{cfg.profile}): #{endpoint}\n")
|
159
|
+
endpoint
|
160
|
+
end
|
161
|
+
|
162
|
+
# check region is a valid RFC host label
|
163
|
+
def validate_region!(region)
|
164
|
+
unless Seahorse::Util.host_label?(region)
|
165
|
+
raise Errors::InvalidRegionError
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def handle_legacy_pseudo_regions(cfg)
|
170
|
+
region = cfg.region
|
171
|
+
new_region = region.gsub('fips-', '').gsub('-fips', '')
|
172
|
+
if region != new_region
|
173
|
+
warn("Legacy region #{region} was transformed to #{new_region}."\
|
174
|
+
'`use_fips_endpoint` config was set to true.')
|
175
|
+
cfg.override_config(:use_fips_endpoint, true)
|
176
|
+
cfg.override_config(:region, new_region)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
# set a default endpoint in config using legacy (endpoints.json) resolver
|
180
|
+
def resolve_legacy_endpoint(cfg)
|
181
|
+
endpoint_prefix = cfg.api.metadata['endpointPrefix']
|
182
|
+
if cfg.respond_to?(:sts_regional_endpoints)
|
183
|
+
sts_regional = cfg.sts_regional_endpoints
|
184
|
+
end
|
185
|
+
|
186
|
+
Aws::Partitions::EndpointProvider.resolve(
|
187
|
+
cfg.region,
|
188
|
+
endpoint_prefix,
|
189
|
+
sts_regional,
|
190
|
+
{
|
191
|
+
dualstack: cfg.use_dualstack_endpoint,
|
192
|
+
fips: cfg.use_fips_endpoint
|
193
|
+
}
|
194
|
+
)
|
195
|
+
end
|
120
196
|
end
|
121
197
|
end
|
122
198
|
end
|
@@ -0,0 +1,217 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Aws
|
4
|
+
module Plugins
|
5
|
+
# @api private
|
6
|
+
class RequestCompression < Seahorse::Client::Plugin
|
7
|
+
DEFAULT_MIN_COMPRESSION_SIZE = 10_240
|
8
|
+
MIN_COMPRESSION_SIZE_LIMIT = 10_485_760
|
9
|
+
SUPPORTED_ENCODINGS = %w[gzip].freeze
|
10
|
+
CHUNK_SIZE = 1 * 1024 * 1024 # one MB
|
11
|
+
|
12
|
+
option(
|
13
|
+
:disable_request_compression,
|
14
|
+
default: false,
|
15
|
+
doc_type: 'Boolean',
|
16
|
+
docstring: <<-DOCS) do |cfg|
|
17
|
+
When set to 'true' the request body will not be compressed
|
18
|
+
for supported operations.
|
19
|
+
DOCS
|
20
|
+
resolve_disable_request_compression(cfg)
|
21
|
+
end
|
22
|
+
|
23
|
+
option(
|
24
|
+
:request_min_compression_size_bytes,
|
25
|
+
default: 10_240,
|
26
|
+
doc_type: 'Integer',
|
27
|
+
docstring: <<-DOCS) do |cfg|
|
28
|
+
The minimum size in bytes that triggers compression for request
|
29
|
+
bodies. The value must be non-negative integer value between 0
|
30
|
+
and 10485780 bytes inclusive.
|
31
|
+
DOCS
|
32
|
+
resolve_request_min_compression_size_bytes(cfg)
|
33
|
+
end
|
34
|
+
|
35
|
+
def after_initialize(client)
|
36
|
+
validate_disable_request_compression_input(client.config)
|
37
|
+
validate_request_min_compression_size_bytes_input(client.config)
|
38
|
+
end
|
39
|
+
|
40
|
+
def validate_disable_request_compression_input(cfg)
|
41
|
+
unless [true, false].include?(cfg.disable_request_compression)
|
42
|
+
raise ArgumentError,
|
43
|
+
'Must provide either `true` or `false` for the '\
|
44
|
+
'`disable_request_compression` configuration option.'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def validate_request_min_compression_size_bytes_input(cfg)
|
49
|
+
value = Integer(cfg.request_min_compression_size_bytes)
|
50
|
+
unless value.between?(0, MIN_COMPRESSION_SIZE_LIMIT)
|
51
|
+
raise ArgumentError,
|
52
|
+
'Must provide a non-negative integer value between '\
|
53
|
+
'`0` and `10485760` bytes inclusive for the '\
|
54
|
+
'`request_min_compression_size_bytes` configuration option.'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def add_handlers(handlers, _config)
|
59
|
+
# priority set to ensure compression happens BEFORE checksum
|
60
|
+
handlers.add(CompressionHandler, priority: 16, step: :build)
|
61
|
+
end
|
62
|
+
|
63
|
+
class << self
|
64
|
+
private
|
65
|
+
|
66
|
+
def resolve_disable_request_compression(cfg)
|
67
|
+
value = ENV['AWS_DISABLE_REQUEST_COMPRESSION'] ||
|
68
|
+
Aws.shared_config.disable_request_compression(profile: cfg.profile) ||
|
69
|
+
'false'
|
70
|
+
Aws::Util.str_2_bool(value)
|
71
|
+
end
|
72
|
+
|
73
|
+
def resolve_request_min_compression_size_bytes(cfg)
|
74
|
+
value = ENV['AWS_REQUEST_MIN_COMPRESSION_SIZE_BYTES'] ||
|
75
|
+
Aws.shared_config.request_min_compression_size_bytes(profile: cfg.profile) ||
|
76
|
+
DEFAULT_MIN_COMPRESSION_SIZE.to_s
|
77
|
+
Integer(value)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# @api private
|
82
|
+
class CompressionHandler < Seahorse::Client::Handler
|
83
|
+
def call(context)
|
84
|
+
if should_compress?(context)
|
85
|
+
selected_encoding = request_encoding_selection(context)
|
86
|
+
if selected_encoding
|
87
|
+
if streaming?(context.operation.input)
|
88
|
+
process_streaming_compression(selected_encoding, context)
|
89
|
+
elsif context.http_request.body.size >= context.config.request_min_compression_size_bytes
|
90
|
+
process_compression(selected_encoding, context)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
@handler.call(context)
|
95
|
+
end
|
96
|
+
|
97
|
+
private
|
98
|
+
|
99
|
+
def request_encoding_selection(context)
|
100
|
+
encoding_list = context.operation.request_compression['encodings']
|
101
|
+
encoding_list.find { |encoding| RequestCompression::SUPPORTED_ENCODINGS.include?(encoding) }
|
102
|
+
end
|
103
|
+
|
104
|
+
def update_content_encoding(encoding, context)
|
105
|
+
headers = context.http_request.headers
|
106
|
+
if headers['Content-Encoding']
|
107
|
+
headers['Content-Encoding'] += ',' + encoding
|
108
|
+
else
|
109
|
+
headers['Content-Encoding'] = encoding
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def should_compress?(context)
|
114
|
+
context.operation.request_compression &&
|
115
|
+
!context.config.disable_request_compression
|
116
|
+
end
|
117
|
+
|
118
|
+
def streaming?(input)
|
119
|
+
if payload = input[:payload_member] # checking ref and shape
|
120
|
+
payload['streaming'] || payload.shape['streaming']
|
121
|
+
else
|
122
|
+
false
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def process_compression(encoding, context)
|
127
|
+
case encoding
|
128
|
+
when 'gzip'
|
129
|
+
gzip_compress(context)
|
130
|
+
else
|
131
|
+
raise StandardError, "We currently do not support #{encoding} encoding"
|
132
|
+
end
|
133
|
+
update_content_encoding(encoding, context)
|
134
|
+
end
|
135
|
+
|
136
|
+
def gzip_compress(context)
|
137
|
+
compressed = StringIO.new
|
138
|
+
compressed.binmode
|
139
|
+
gzip_writer = Zlib::GzipWriter.new(compressed)
|
140
|
+
if context.http_request.body.respond_to?(:read)
|
141
|
+
update_in_chunks(gzip_writer, context.http_request.body)
|
142
|
+
else
|
143
|
+
gzip_writer.write(context.http_request.body)
|
144
|
+
end
|
145
|
+
gzip_writer.close
|
146
|
+
new_body = StringIO.new(compressed.string)
|
147
|
+
context.http_request.body = new_body
|
148
|
+
end
|
149
|
+
|
150
|
+
def update_in_chunks(compressor, io)
|
151
|
+
loop do
|
152
|
+
chunk = io.read(CHUNK_SIZE)
|
153
|
+
break unless chunk
|
154
|
+
|
155
|
+
compressor.write(chunk)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def process_streaming_compression(encoding, context)
|
160
|
+
case encoding
|
161
|
+
when 'gzip'
|
162
|
+
context.http_request.body = GzipIO.new(context.http_request.body)
|
163
|
+
else
|
164
|
+
raise StandardError, "We currently do not support #{encoding} encoding"
|
165
|
+
end
|
166
|
+
update_content_encoding(encoding, context)
|
167
|
+
end
|
168
|
+
|
169
|
+
# @api private
|
170
|
+
class GzipIO
|
171
|
+
def initialize(body)
|
172
|
+
@body = body
|
173
|
+
@buffer = ChunkBuffer.new
|
174
|
+
@gzip_writer = Zlib::GzipWriter.new(@buffer)
|
175
|
+
end
|
176
|
+
|
177
|
+
def read(length, buff = nil)
|
178
|
+
if @gzip_writer.closed?
|
179
|
+
# an empty string to signify an end as
|
180
|
+
# there will be nothing remaining to be read
|
181
|
+
StringIO.new('').read(length, buff)
|
182
|
+
return
|
183
|
+
end
|
184
|
+
|
185
|
+
chunk = @body.read(length)
|
186
|
+
if !chunk || chunk.empty?
|
187
|
+
# closing the writer will write one last chunk
|
188
|
+
# with a trailer (to be read from the @buffer)
|
189
|
+
@gzip_writer.close
|
190
|
+
else
|
191
|
+
# flush happens first to ensure that header fields
|
192
|
+
# are being sent over since write will override
|
193
|
+
@gzip_writer.flush
|
194
|
+
@gzip_writer.write(chunk)
|
195
|
+
end
|
196
|
+
|
197
|
+
StringIO.new(@buffer.last_chunk).read(length, buff)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
# @api private
|
202
|
+
class ChunkBuffer
|
203
|
+
def initialize
|
204
|
+
@last_chunk = nil
|
205
|
+
end
|
206
|
+
|
207
|
+
attr_reader :last_chunk
|
208
|
+
|
209
|
+
def write(data)
|
210
|
+
@last_chunk = data
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
@@ -108,6 +108,7 @@ module Aws
|
|
108
108
|
credentials_provider: config.credentials,
|
109
109
|
signing_algorithm: scheme_name.to_sym,
|
110
110
|
uri_escape_path: !!!auth_scheme['disableDoubleEncoding'],
|
111
|
+
normalize_path: !!!auth_scheme['disableNormalizePath'],
|
111
112
|
unsigned_headers: %w[content-length user-agent x-amzn-trace-id]
|
112
113
|
)
|
113
114
|
rescue Aws::Sigv4::Errors::MissingCredentialsError
|
@@ -4,7 +4,31 @@ module Aws
|
|
4
4
|
module Plugins
|
5
5
|
# @api private
|
6
6
|
class UserAgent < Seahorse::Client::Plugin
|
7
|
+
# @api private
|
7
8
|
option(:user_agent_suffix)
|
9
|
+
# @api private
|
10
|
+
option(:user_agent_frameworks, default: [])
|
11
|
+
|
12
|
+
option(
|
13
|
+
:sdk_ua_app_id,
|
14
|
+
doc_type: 'String',
|
15
|
+
docstring: <<-DOCS) do |cfg|
|
16
|
+
A unique and opaque application ID that is appended to the
|
17
|
+
User-Agent header as app/<sdk_ua_app_id>. It should have a
|
18
|
+
maximum length of 50.
|
19
|
+
DOCS
|
20
|
+
app_id = ENV['AWS_SDK_UA_APP_ID']
|
21
|
+
app_id ||= Aws.shared_config.sdk_ua_app_id(profile: cfg.profile)
|
22
|
+
app_id
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.feature(feature, &block)
|
26
|
+
Thread.current[:aws_sdk_core_user_agent_feature] ||= []
|
27
|
+
Thread.current[:aws_sdk_core_user_agent_feature] << "ft/#{feature}"
|
28
|
+
block.call
|
29
|
+
ensure
|
30
|
+
Thread.current[:aws_sdk_core_user_agent_feature].pop
|
31
|
+
end
|
8
32
|
|
9
33
|
# @api private
|
10
34
|
class Handler < Seahorse::Client::Handler
|
@@ -14,33 +38,112 @@ module Aws
|
|
14
38
|
end
|
15
39
|
|
16
40
|
def set_user_agent(context)
|
17
|
-
|
41
|
+
context.http_request.headers['User-Agent'] = UserAgent.new(context).to_s
|
42
|
+
end
|
43
|
+
|
44
|
+
class UserAgent
|
45
|
+
def initialize(context)
|
46
|
+
@context = context
|
47
|
+
end
|
48
|
+
|
49
|
+
def to_s
|
50
|
+
ua = "aws-sdk-ruby3/#{CORE_GEM_VERSION}"
|
51
|
+
ua += ' ua/2.0'
|
52
|
+
ua += " #{api_metadata}" if api_metadata
|
53
|
+
ua += " #{os_metadata}"
|
54
|
+
ua += " #{language_metadata}"
|
55
|
+
ua += " #{env_metadata}" if env_metadata
|
56
|
+
ua += " #{config_metadata}" if config_metadata
|
57
|
+
ua += " #{app_id}" if app_id
|
58
|
+
ua += " #{feature_metadata}" if feature_metadata
|
59
|
+
ua += " #{framework_metadata}" if framework_metadata
|
60
|
+
if @context.config.user_agent_suffix
|
61
|
+
ua += " #{@context.config.user_agent_suffix}"
|
62
|
+
end
|
63
|
+
ua.strip
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
18
67
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
68
|
+
# Used to be gem_name/gem_version
|
69
|
+
def api_metadata
|
70
|
+
service_id = @context.config.api.metadata['serviceId']
|
71
|
+
return unless service_id
|
72
|
+
|
73
|
+
service_id = service_id.gsub(' ', '_').downcase
|
74
|
+
gem_version = @context[:gem_version]
|
75
|
+
"api/#{service_id}##{gem_version}"
|
76
|
+
end
|
77
|
+
|
78
|
+
# Used to be RUBY_PLATFORM
|
79
|
+
def os_metadata
|
80
|
+
os =
|
81
|
+
case RbConfig::CONFIG['host_os']
|
82
|
+
when /mac|darwin/
|
83
|
+
'macos'
|
84
|
+
when /linux|cygwin/
|
85
|
+
'linux'
|
86
|
+
when /mingw|mswin/
|
87
|
+
'windows'
|
88
|
+
else
|
89
|
+
'other'
|
90
|
+
end
|
91
|
+
metadata = "os/#{os}"
|
92
|
+
local_version = Gem::Platform.local.version
|
93
|
+
metadata += "##{local_version}" if local_version
|
94
|
+
metadata += " md/#{RbConfig::CONFIG['host_cpu']}"
|
95
|
+
metadata
|
23
96
|
end
|
24
97
|
|
25
|
-
|
98
|
+
# Used to be RUBY_ENGINE/RUBY_VERSION
|
99
|
+
def language_metadata
|
100
|
+
"lang/#{RUBY_ENGINE}##{RUBY_ENGINE_VERSION} md/#{RUBY_VERSION}"
|
101
|
+
end
|
102
|
+
|
103
|
+
def env_metadata
|
104
|
+
return unless (execution_env = ENV['AWS_EXECUTION_ENV'])
|
105
|
+
|
106
|
+
"exec-env/#{execution_env}"
|
107
|
+
end
|
26
108
|
|
27
|
-
|
28
|
-
|
109
|
+
def config_metadata
|
110
|
+
"cfg/retry-mode##{@context.config.retry_mode}"
|
29
111
|
end
|
30
112
|
|
31
|
-
|
32
|
-
|
113
|
+
def app_id
|
114
|
+
return unless (app_id = @context.config.sdk_ua_app_id)
|
115
|
+
|
116
|
+
# Sanitize and only allow these characters
|
117
|
+
app_id = app_id.gsub(/[^!#$%&'*+\-.^_`|~0-9A-Za-z]/, '-')
|
118
|
+
"app/#{app_id}"
|
33
119
|
end
|
34
120
|
|
35
|
-
|
36
|
-
|
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(' ')
|
37
125
|
end
|
38
126
|
|
39
|
-
|
127
|
+
def framework_metadata
|
128
|
+
if (frameworks_cfg = @context.config.user_agent_frameworks).empty?
|
129
|
+
return
|
130
|
+
end
|
131
|
+
|
132
|
+
# Frameworks may be aws-record, aws-sdk-rails, etc.
|
133
|
+
regex = /gems\/(?<name>#{frameworks_cfg.join('|')})-(?<version>\d+\.\d+\.\d+)/.freeze
|
134
|
+
frameworks = {}
|
135
|
+
Kernel.caller.each do |line|
|
136
|
+
match = line.match(regex)
|
137
|
+
next unless match
|
138
|
+
|
139
|
+
frameworks[match[:name]] = match[:version]
|
140
|
+
end
|
141
|
+
frameworks.map { |n, v| "lib/#{n}##{v}" }.join(' ')
|
142
|
+
end
|
40
143
|
end
|
41
144
|
end
|
42
145
|
|
43
|
-
handler(Handler)
|
146
|
+
handler(Handler, priority: 1)
|
44
147
|
end
|
45
148
|
end
|
46
149
|
end
|
@@ -4,9 +4,16 @@ module Aws
|
|
4
4
|
module Rest
|
5
5
|
module Request
|
6
6
|
class QuerystringBuilder
|
7
|
-
|
8
7
|
include Seahorse::Model::Shapes
|
9
8
|
|
9
|
+
SUPPORTED_TYPES = [
|
10
|
+
BooleanShape,
|
11
|
+
FloatShape,
|
12
|
+
IntegerShape,
|
13
|
+
StringShape,
|
14
|
+
TimestampShape
|
15
|
+
].freeze
|
16
|
+
|
10
17
|
# Provide shape references and param values:
|
11
18
|
#
|
12
19
|
# [
|
@@ -33,29 +40,12 @@ module Aws
|
|
33
40
|
def build_part(shape_ref, param_value)
|
34
41
|
case shape_ref.shape
|
35
42
|
# supported scalar types
|
36
|
-
when
|
37
|
-
|
38
|
-
"#{param_name}=#{escape(param_value.to_s)}"
|
39
|
-
when TimestampShape
|
40
|
-
param_name = shape_ref.location_name
|
41
|
-
"#{param_name}=#{escape(timestamp(shape_ref, param_value))}"
|
43
|
+
when *SUPPORTED_TYPES
|
44
|
+
"#{shape_ref.location_name}=#{query_value(shape_ref, param_value)}"
|
42
45
|
when MapShape
|
43
|
-
|
44
|
-
query_map_of_string(param_value)
|
45
|
-
elsif ListShape === shape_ref.shape.value.shape
|
46
|
-
query_map_of_string_list(param_value)
|
47
|
-
else
|
48
|
-
msg = "only map of string and string list supported"
|
49
|
-
raise NotImplementedError, msg
|
50
|
-
end
|
46
|
+
generate_query_map(shape_ref, param_value)
|
51
47
|
when ListShape
|
52
|
-
|
53
|
-
list_of_strings(shape_ref.location_name, param_value)
|
54
|
-
else
|
55
|
-
msg = "Only list of strings supported, got "\
|
56
|
-
"#{shape_ref.shape.member.shape.class.name}"
|
57
|
-
raise NotImplementedError, msg
|
58
|
-
end
|
48
|
+
generate_query_list(shape_ref, param_value)
|
59
49
|
else
|
60
50
|
raise NotImplementedError
|
61
51
|
end
|
@@ -71,6 +61,37 @@ module Aws
|
|
71
61
|
end
|
72
62
|
end
|
73
63
|
|
64
|
+
def query_value(ref, value)
|
65
|
+
case ref.shape
|
66
|
+
when TimestampShape
|
67
|
+
escape(timestamp(ref, value))
|
68
|
+
when *SUPPORTED_TYPES
|
69
|
+
escape(value.to_s)
|
70
|
+
else
|
71
|
+
raise NotImplementedError
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def generate_query_list(ref, values)
|
76
|
+
member_ref = ref.shape.member
|
77
|
+
values.map do |value|
|
78
|
+
value = query_value(member_ref, value)
|
79
|
+
"#{ref.location_name}=#{value}"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def generate_query_map(ref, value)
|
84
|
+
case ref.shape.value.shape
|
85
|
+
when StringShape
|
86
|
+
query_map_of_string(value)
|
87
|
+
when ListShape
|
88
|
+
query_map_of_string_list(value)
|
89
|
+
else
|
90
|
+
msg = 'Only map of string and string list supported'
|
91
|
+
raise NotImplementedError, msg
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
74
95
|
def query_map_of_string(hash)
|
75
96
|
list = []
|
76
97
|
hash.each_pair do |key, value|
|
@@ -89,16 +110,9 @@ module Aws
|
|
89
110
|
list
|
90
111
|
end
|
91
112
|
|
92
|
-
def list_of_strings(name, values)
|
93
|
-
values.map do |value|
|
94
|
-
"#{name}=#{escape(value)}"
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
113
|
def escape(string)
|
99
114
|
Seahorse::Util.uri_escape(string)
|
100
115
|
end
|
101
|
-
|
102
116
|
end
|
103
117
|
end
|
104
118
|
end
|