aws-sdk-core 3.117.0 → 3.197.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +836 -0
- data/VERSION +1 -1
- data/lib/aws-defaults/default_configuration.rb +153 -0
- data/lib/aws-defaults/defaults_mode_config_resolver.rb +107 -0
- data/lib/aws-defaults.rb +3 -0
- data/lib/aws-sdk-core/arn.rb +13 -0
- data/lib/aws-sdk-core/assume_role_credentials.rb +21 -7
- data/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +14 -10
- data/lib/aws-sdk-core/binary/decode_handler.rb +0 -5
- data/lib/aws-sdk-core/binary/encode_handler.rb +12 -1
- data/lib/aws-sdk-core/binary/event_builder.rb +34 -37
- data/lib/aws-sdk-core/client_stubs.rb +20 -13
- data/lib/aws-sdk-core/credential_provider.rb +4 -1
- data/lib/aws-sdk-core/credential_provider_chain.rb +8 -5
- data/lib/aws-sdk-core/ec2_metadata.rb +4 -3
- data/lib/aws-sdk-core/ecs_credentials.rb +187 -52
- data/lib/aws-sdk-core/endpoints/condition.rb +41 -0
- data/lib/aws-sdk-core/endpoints/endpoint.rb +17 -0
- data/lib/aws-sdk-core/endpoints/endpoint_rule.rb +75 -0
- data/lib/aws-sdk-core/endpoints/error_rule.rb +42 -0
- data/lib/aws-sdk-core/endpoints/function.rb +80 -0
- data/lib/aws-sdk-core/endpoints/matchers.rb +135 -0
- data/lib/aws-sdk-core/endpoints/reference.rb +31 -0
- data/lib/aws-sdk-core/endpoints/rule.rb +25 -0
- data/lib/aws-sdk-core/endpoints/rule_set.rb +52 -0
- data/lib/aws-sdk-core/endpoints/rules_provider.rb +37 -0
- data/lib/aws-sdk-core/endpoints/templater.rb +58 -0
- data/lib/aws-sdk-core/endpoints/tree_rule.rb +45 -0
- data/lib/aws-sdk-core/endpoints/url.rb +60 -0
- data/lib/aws-sdk-core/endpoints.rb +78 -0
- data/lib/aws-sdk-core/errors.rb +17 -4
- data/lib/aws-sdk-core/event_emitter.rb +0 -16
- data/lib/aws-sdk-core/ini_parser.rb +7 -0
- data/lib/aws-sdk-core/instance_profile_credentials.rb +127 -33
- data/lib/aws-sdk-core/json/builder.rb +8 -1
- data/lib/aws-sdk-core/json/error_handler.rb +30 -4
- data/lib/aws-sdk-core/json/handler.rb +8 -1
- data/lib/aws-sdk-core/json/json_engine.rb +10 -8
- data/lib/aws-sdk-core/json/oj_engine.rb +33 -6
- data/lib/aws-sdk-core/json/parser.rb +38 -2
- data/lib/aws-sdk-core/json.rb +8 -26
- data/lib/aws-sdk-core/log/formatter.rb +6 -0
- data/lib/aws-sdk-core/log/param_filter.rb +9 -1
- data/lib/aws-sdk-core/lru_cache.rb +75 -0
- data/lib/aws-sdk-core/pageable_response.rb +81 -32
- data/lib/aws-sdk-core/param_validator.rb +36 -2
- data/lib/aws-sdk-core/plugins/bearer_authorization.rb +67 -0
- data/lib/aws-sdk-core/plugins/checksum_algorithm.rb +342 -0
- data/lib/aws-sdk-core/plugins/client_metrics_plugin.rb +1 -0
- data/lib/aws-sdk-core/plugins/client_metrics_send_plugin.rb +14 -2
- data/lib/aws-sdk-core/plugins/credentials_configuration.rb +29 -1
- data/lib/aws-sdk-core/plugins/defaults_mode.rb +40 -0
- data/lib/aws-sdk-core/plugins/endpoint_discovery.rb +6 -2
- data/lib/aws-sdk-core/plugins/http_checksum.rb +9 -1
- data/lib/aws-sdk-core/plugins/invocation_id.rb +1 -11
- data/lib/aws-sdk-core/plugins/jsonvalue_converter.rb +34 -6
- data/lib/aws-sdk-core/plugins/logging.rb +2 -0
- data/lib/aws-sdk-core/plugins/protocols/api_gateway.rb +17 -0
- data/lib/aws-sdk-core/plugins/protocols/rest_json.rb +4 -2
- data/lib/aws-sdk-core/plugins/protocols/rest_xml.rb +1 -2
- data/lib/aws-sdk-core/plugins/recursion_detection.rb +38 -0
- data/lib/aws-sdk-core/plugins/regional_endpoint.rb +144 -17
- data/lib/aws-sdk-core/plugins/request_compression.rb +226 -0
- data/lib/aws-sdk-core/plugins/response_paging.rb +1 -1
- data/lib/aws-sdk-core/plugins/retries/error_inspector.rb +7 -4
- data/lib/aws-sdk-core/plugins/retry_errors.rb +33 -7
- data/lib/aws-sdk-core/plugins/sign.rb +211 -0
- data/lib/aws-sdk-core/plugins/signature_v2.rb +1 -0
- data/lib/aws-sdk-core/plugins/signature_v4.rb +28 -31
- data/lib/aws-sdk-core/plugins/stub_responses.rb +6 -1
- data/lib/aws-sdk-core/plugins/user_agent.rb +152 -14
- data/lib/aws-sdk-core/process_credentials.rb +50 -34
- data/lib/aws-sdk-core/query/ec2_param_builder.rb +5 -7
- data/lib/aws-sdk-core/query/param_builder.rb +2 -2
- data/lib/aws-sdk-core/refreshing_credentials.rb +49 -18
- data/lib/aws-sdk-core/refreshing_token.rb +71 -0
- data/lib/aws-sdk-core/rest/handler.rb +1 -1
- data/lib/aws-sdk-core/rest/request/body.rb +49 -4
- data/lib/aws-sdk-core/rest/request/content_type.rb +60 -0
- data/lib/aws-sdk-core/rest/request/endpoint.rb +24 -4
- data/lib/aws-sdk-core/rest/request/headers.rb +23 -7
- data/lib/aws-sdk-core/rest/request/querystring_builder.rb +62 -36
- 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 +10 -3
- data/lib/aws-sdk-core/rest.rb +1 -0
- data/lib/aws-sdk-core/shared_config.rb +112 -12
- data/lib/aws-sdk-core/sso_credentials.rb +92 -51
- data/lib/aws-sdk-core/sso_token_provider.rb +135 -0
- data/lib/aws-sdk-core/static_token_provider.rb +14 -0
- data/lib/aws-sdk-core/structure.rb +16 -5
- data/lib/aws-sdk-core/stubbing/stub_data.rb +11 -0
- data/lib/aws-sdk-core/token.rb +31 -0
- data/lib/aws-sdk-core/token_provider.rb +15 -0
- data/lib/aws-sdk-core/token_provider_chain.rb +51 -0
- data/lib/aws-sdk-core/util.rb +39 -0
- data/lib/aws-sdk-core/waiters/poller.rb +4 -2
- data/lib/aws-sdk-core/xml/builder.rb +17 -9
- data/lib/aws-sdk-core/xml/error_handler.rb +31 -8
- data/lib/aws-sdk-core/xml/parser/engines/oga.rb +2 -0
- data/lib/aws-sdk-core/xml/parser/engines/ox.rb +1 -1
- data/lib/aws-sdk-core/xml/parser/engines/rexml.rb +0 -8
- data/lib/aws-sdk-core/xml/parser/frame.rb +27 -20
- data/lib/aws-sdk-core/xml/parser/stack.rb +2 -0
- data/lib/aws-sdk-core.rb +21 -0
- data/lib/aws-sdk-sso/client.rb +157 -50
- data/lib/aws-sdk-sso/endpoint_parameters.rb +66 -0
- data/lib/aws-sdk-sso/endpoint_provider.rb +57 -0
- data/lib/aws-sdk-sso/endpoints.rb +72 -0
- data/lib/aws-sdk-sso/plugins/endpoints.rb +78 -0
- data/lib/aws-sdk-sso/types.rb +8 -43
- data/lib/aws-sdk-sso.rb +5 -1
- data/lib/aws-sdk-ssooidc/client.rb +1008 -0
- data/lib/aws-sdk-ssooidc/client_api.rb +293 -0
- data/lib/aws-sdk-ssooidc/customizations.rb +1 -0
- data/lib/aws-sdk-ssooidc/endpoint_parameters.rb +66 -0
- data/lib/aws-sdk-ssooidc/endpoint_provider.rb +57 -0
- data/lib/aws-sdk-ssooidc/endpoints.rb +72 -0
- data/lib/aws-sdk-ssooidc/errors.rb +342 -0
- data/lib/aws-sdk-ssooidc/plugins/endpoints.rb +78 -0
- data/lib/aws-sdk-ssooidc/resource.rb +26 -0
- data/lib/aws-sdk-ssooidc/types.rb +823 -0
- data/lib/aws-sdk-ssooidc.rb +59 -0
- data/lib/aws-sdk-sts/client.rb +472 -398
- data/lib/aws-sdk-sts/client_api.rb +20 -9
- data/lib/aws-sdk-sts/endpoint_parameters.rb +78 -0
- data/lib/aws-sdk-sts/endpoint_provider.rb +112 -0
- data/lib/aws-sdk-sts/endpoints.rb +136 -0
- data/lib/aws-sdk-sts/plugins/endpoints.rb +86 -0
- data/lib/aws-sdk-sts/plugins/sts_regional_endpoints.rb +5 -1
- data/lib/aws-sdk-sts/presigner.rb +14 -10
- data/lib/aws-sdk-sts/types.rb +168 -227
- data/lib/aws-sdk-sts.rb +5 -1
- data/lib/seahorse/client/async_base.rb +1 -2
- data/lib/seahorse/client/async_response.rb +19 -0
- data/lib/seahorse/client/base.rb +1 -0
- data/lib/seahorse/client/configuration.rb +5 -5
- data/lib/seahorse/client/h2/connection.rb +15 -16
- data/lib/seahorse/client/h2/handler.rb +5 -5
- data/lib/seahorse/client/net_http/connection_pool.rb +10 -9
- data/lib/seahorse/client/net_http/handler.rb +15 -7
- data/lib/seahorse/client/net_http/patches.rb +12 -86
- data/lib/seahorse/client/plugin.rb +9 -0
- data/lib/seahorse/client/plugins/content_length.rb +11 -5
- data/lib/seahorse/client/plugins/h2.rb +3 -3
- data/lib/seahorse/client/plugins/net_http.rb +73 -10
- data/lib/seahorse/client/plugins/request_callback.rb +40 -9
- data/lib/seahorse/client/response.rb +6 -0
- data/lib/seahorse/model/operation.rb +6 -0
- data/lib/seahorse/model/shapes.rb +27 -2
- data/lib/seahorse/util.rb +4 -0
- data/sig/aws-sdk-core/client_stubs.rbs +10 -0
- data/sig/aws-sdk-core/errors.rbs +22 -0
- data/sig/aws-sdk-core/resources/collection.rbs +21 -0
- data/sig/aws-sdk-core/structure.rbs +4 -0
- data/sig/aws-sdk-core/waiters/errors.rbs +20 -0
- data/sig/aws-sdk-core.rbs +7 -0
- data/sig/seahorse/client/base.rbs +25 -0
- data/sig/seahorse/client/handler_builder.rbs +16 -0
- data/sig/seahorse/client/response.rbs +61 -0
- metadata +82 -17
- data/lib/aws-sdk-sso/plugins/content_type.rb +0 -25
@@ -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)
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'thread'
|
4
|
-
|
5
3
|
module Aws
|
6
4
|
|
7
5
|
# Base class used credential classes that can be refreshed. This
|
@@ -17,45 +15,78 @@ module Aws
|
|
17
15
|
# @api private
|
18
16
|
module RefreshingCredentials
|
19
17
|
|
18
|
+
SYNC_EXPIRATION_LENGTH = 300 # 5 minutes
|
19
|
+
ASYNC_EXPIRATION_LENGTH = 600 # 10 minutes
|
20
|
+
|
21
|
+
CLIENT_EXCLUDE_OPTIONS = Set.new([:before_refresh]).freeze
|
22
|
+
|
20
23
|
def initialize(options = {})
|
21
24
|
@mutex = Mutex.new
|
25
|
+
@before_refresh = options.delete(:before_refresh) if Hash === options
|
26
|
+
|
27
|
+
@before_refresh.call(self) if @before_refresh
|
22
28
|
refresh
|
23
29
|
end
|
24
30
|
|
25
31
|
# @return [Credentials]
|
26
32
|
def credentials
|
27
|
-
refresh_if_near_expiration
|
33
|
+
refresh_if_near_expiration!
|
28
34
|
@credentials
|
29
35
|
end
|
30
36
|
|
31
|
-
# @return [Time,nil]
|
32
|
-
def expiration
|
33
|
-
refresh_if_near_expiration
|
34
|
-
@expiration
|
35
|
-
end
|
36
|
-
|
37
37
|
# Refresh credentials.
|
38
38
|
# @return [void]
|
39
39
|
def refresh!
|
40
|
-
@mutex.synchronize
|
40
|
+
@mutex.synchronize do
|
41
|
+
@before_refresh.call(self) if @before_refresh
|
42
|
+
|
43
|
+
refresh
|
44
|
+
end
|
41
45
|
end
|
42
46
|
|
43
47
|
private
|
44
48
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
+
def sync_expiration_length
|
50
|
+
self.class::SYNC_EXPIRATION_LENGTH
|
51
|
+
end
|
52
|
+
|
53
|
+
def async_expiration_length
|
54
|
+
self.class::ASYNC_EXPIRATION_LENGTH
|
55
|
+
end
|
56
|
+
|
57
|
+
# Refreshes credentials asynchronously and synchronously.
|
58
|
+
# If we are near to expiration, block while getting new credentials.
|
59
|
+
# Otherwise, if we're approaching expiration, use the existing credentials
|
60
|
+
# but attempt a refresh in the background.
|
61
|
+
def refresh_if_near_expiration!
|
62
|
+
# Note: This check is an optimization. Rather than acquire the mutex on every #refresh_if_near_expiration
|
63
|
+
# call, we check before doing so, and then we check within the mutex to avoid a race condition.
|
64
|
+
# See issue: https://github.com/aws/aws-sdk-ruby/issues/2641 for more info.
|
65
|
+
if near_expiration?(sync_expiration_length)
|
49
66
|
@mutex.synchronize do
|
50
|
-
|
67
|
+
if near_expiration?(sync_expiration_length)
|
68
|
+
@before_refresh.call(self) if @before_refresh
|
69
|
+
refresh
|
70
|
+
end
|
71
|
+
end
|
72
|
+
elsif @async_refresh && near_expiration?(async_expiration_length)
|
73
|
+
unless @mutex.locked?
|
74
|
+
Thread.new do
|
75
|
+
@mutex.synchronize do
|
76
|
+
if near_expiration?(async_expiration_length)
|
77
|
+
@before_refresh.call(self) if @before_refresh
|
78
|
+
refresh
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
51
82
|
end
|
52
83
|
end
|
53
84
|
end
|
54
85
|
|
55
|
-
def near_expiration?
|
86
|
+
def near_expiration?(expiration_length)
|
56
87
|
if @expiration
|
57
|
-
#
|
58
|
-
(Time.now.to_i +
|
88
|
+
# Are we within expiration?
|
89
|
+
(Time.now.to_i + expiration_length) > @expiration.to_i
|
59
90
|
else
|
60
91
|
true
|
61
92
|
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'thread'
|
4
|
+
|
5
|
+
module Aws
|
6
|
+
|
7
|
+
# Module/mixin used by token provider classes that can be refreshed. This
|
8
|
+
# provides basic refresh logic in a thread-safe manner. Classes mixing in
|
9
|
+
# this module are expected to implement a #refresh method that populates
|
10
|
+
# the following instance variable:
|
11
|
+
#
|
12
|
+
# * `@token` [Token] - {Aws::Token} object with the `expiration` and `token`
|
13
|
+
# fields set.
|
14
|
+
#
|
15
|
+
# @api private
|
16
|
+
module RefreshingToken
|
17
|
+
|
18
|
+
def initialize(options = {})
|
19
|
+
@mutex = Mutex.new
|
20
|
+
@before_refresh = options.delete(:before_refresh) if Hash === options
|
21
|
+
|
22
|
+
@before_refresh.call(self) if @before_refresh
|
23
|
+
refresh
|
24
|
+
end
|
25
|
+
|
26
|
+
# @return [Token]
|
27
|
+
def token
|
28
|
+
refresh_if_near_expiration
|
29
|
+
@token
|
30
|
+
end
|
31
|
+
|
32
|
+
# @return [Time,nil]
|
33
|
+
def expiration
|
34
|
+
refresh_if_near_expiration
|
35
|
+
@expiration
|
36
|
+
end
|
37
|
+
|
38
|
+
# Refresh token.
|
39
|
+
# @return [void]
|
40
|
+
def refresh!
|
41
|
+
@mutex.synchronize do
|
42
|
+
@before_refresh.call(self) if @before_refresh
|
43
|
+
refresh
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
# Refreshes token if it is within
|
50
|
+
# 5 minutes of expiration.
|
51
|
+
def refresh_if_near_expiration
|
52
|
+
if near_expiration?
|
53
|
+
@mutex.synchronize do
|
54
|
+
if near_expiration?
|
55
|
+
@before_refresh.call(self) if @before_refresh
|
56
|
+
refresh
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def near_expiration?
|
63
|
+
if @token && @token.expiration
|
64
|
+
# are we within 5 minutes of expiration?
|
65
|
+
(Time.now.to_i + 5 * 60) > @token.expiration.to_i
|
66
|
+
else
|
67
|
+
true
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -17,23 +17,60 @@ module Aws
|
|
17
17
|
# @param [Seahorse::Client::Http::Request] http_req
|
18
18
|
# @param [Hash] params
|
19
19
|
def apply(http_req, params)
|
20
|
-
|
20
|
+
body = build_body(params)
|
21
|
+
|
22
|
+
# for rest-json, ensure we send at least an empty object
|
23
|
+
# don't send an empty object for streaming? case.
|
24
|
+
if body.nil? &&
|
25
|
+
json_builder? &&
|
26
|
+
modeled_body? &&
|
27
|
+
!streaming?
|
28
|
+
body = '{}'
|
29
|
+
end
|
30
|
+
http_req.body = body
|
21
31
|
end
|
22
32
|
|
23
33
|
private
|
24
34
|
|
35
|
+
# operation is modeled for body when it is modeled for a payload
|
36
|
+
# either with payload trait or normal members.
|
37
|
+
def modeled_body?
|
38
|
+
return true if @rules[:payload]
|
39
|
+
@rules.shape.members.each do |member|
|
40
|
+
_name, shape = member
|
41
|
+
return true if shape.location.nil?
|
42
|
+
end
|
43
|
+
false
|
44
|
+
end
|
45
|
+
|
25
46
|
def build_body(params)
|
26
47
|
if streaming?
|
27
48
|
params[@rules[:payload]]
|
28
49
|
elsif @rules[:payload]
|
29
50
|
params = params[@rules[:payload]]
|
30
|
-
|
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
|
31
63
|
else
|
32
64
|
params = body_params(params)
|
33
65
|
serialize(@rules, params) unless params.empty?
|
34
66
|
end
|
35
67
|
end
|
36
68
|
|
69
|
+
def payload_location_name
|
70
|
+
@rules[:payload_member].shape['locationName'] ||
|
71
|
+
@rules[:payload_member].shape.name
|
72
|
+
end
|
73
|
+
|
37
74
|
def streaming?
|
38
75
|
@rules[:payload] && (
|
39
76
|
BlobShape === @rules[:payload_member].shape ||
|
@@ -41,8 +78,16 @@ module Aws
|
|
41
78
|
)
|
42
79
|
end
|
43
80
|
|
44
|
-
def
|
45
|
-
@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)
|
46
91
|
end
|
47
92
|
|
48
93
|
def body_params(params)
|
@@ -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 ref 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
|
@@ -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)
|
@@ -32,11 +33,11 @@ module Aws
|
|
32
33
|
|
33
34
|
def apply_header_value(headers, ref, value)
|
34
35
|
value = apply_json_trait(value) if ref['jsonvalue']
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
36
|
+
case ref.shape
|
37
|
+
when TimestampShape then headers[ref.location_name] = timestamp(ref, value)
|
38
|
+
when ListShape then list(headers, ref, value)
|
39
|
+
else headers[ref.location_name] = value.to_s
|
40
|
+
end
|
40
41
|
end
|
41
42
|
|
42
43
|
def timestamp(ref, value)
|
@@ -49,6 +50,21 @@ module Aws
|
|
49
50
|
end
|
50
51
|
end
|
51
52
|
|
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(', ')
|
66
|
+
end
|
67
|
+
|
52
68
|
def apply_header_map(headers, ref, values)
|
53
69
|
prefix = ref.location_name || ''
|
54
70
|
values.each_pair do |name, value|
|
@@ -57,7 +73,7 @@ module Aws
|
|
57
73
|
end
|
58
74
|
|
59
75
|
# With complex headers value in json syntax,
|
60
|
-
# base64 encodes value to
|
76
|
+
# base64 encodes value to avoid weird characters
|
61
77
|
# causing potential issues in headers
|
62
78
|
def apply_json_trait(value)
|
63
79
|
Base64.strict_encode64(value)
|
@@ -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
|
# [
|
@@ -23,39 +30,32 @@ module Aws
|
|
23
30
|
#
|
24
31
|
# @return [String] Returns a built querystring
|
25
32
|
def build(params)
|
33
|
+
# keys in query maps must NOT override other keys
|
34
|
+
query_keys = query_keys(params)
|
26
35
|
params.map do |(shape_ref, param_value)|
|
27
|
-
build_part(shape_ref, param_value)
|
28
|
-
end.join('&')
|
36
|
+
build_part(shape_ref, param_value, query_keys)
|
37
|
+
end.reject { |p| p.nil? || p.empty? }.join('&')
|
29
38
|
end
|
30
39
|
|
31
40
|
private
|
32
41
|
|
33
|
-
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)
|
34
51
|
case shape_ref.shape
|
35
52
|
# 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))}"
|
53
|
+
when *SUPPORTED_TYPES
|
54
|
+
"#{shape_ref.location_name}=#{query_value(shape_ref, param_value)}"
|
42
55
|
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
|
56
|
+
generate_query_map(shape_ref, param_value, query_keys)
|
51
57
|
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
|
58
|
+
generate_query_list(shape_ref, param_value)
|
59
59
|
else
|
60
60
|
raise NotImplementedError
|
61
61
|
end
|
@@ -71,34 +71,60 @@ module Aws
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
-
def
|
74
|
+
def query_value(ref, value)
|
75
|
+
case ref.shape
|
76
|
+
when TimestampShape
|
77
|
+
escape(timestamp(ref, value))
|
78
|
+
when *SUPPORTED_TYPES
|
79
|
+
escape(value.to_s)
|
80
|
+
else
|
81
|
+
raise NotImplementedError
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def generate_query_list(ref, values)
|
86
|
+
member_ref = ref.shape.member
|
87
|
+
values.map do |value|
|
88
|
+
value = query_value(member_ref, value)
|
89
|
+
"#{ref.location_name}=#{value}"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def generate_query_map(ref, value, query_keys)
|
94
|
+
case ref.shape.value.shape
|
95
|
+
when StringShape
|
96
|
+
query_map_of_string(value, query_keys)
|
97
|
+
when ListShape
|
98
|
+
query_map_of_string_list(value, query_keys)
|
99
|
+
else
|
100
|
+
msg = 'Only map of string and string list supported'
|
101
|
+
raise NotImplementedError, msg
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def query_map_of_string(hash, query_keys)
|
75
106
|
list = []
|
76
107
|
hash.each_pair do |key, value|
|
77
|
-
|
108
|
+
key = escape(key)
|
109
|
+
list << "#{key}=#{escape(value)}" unless query_keys.include?(key)
|
78
110
|
end
|
79
111
|
list
|
80
112
|
end
|
81
113
|
|
82
|
-
def query_map_of_string_list(hash)
|
114
|
+
def query_map_of_string_list(hash, query_keys)
|
83
115
|
list = []
|
84
116
|
hash.each_pair do |key, values|
|
117
|
+
key = escape(key)
|
85
118
|
values.each do |value|
|
86
|
-
list << "#{
|
119
|
+
list << "#{key}=#{escape(value)}" unless query_keys.include?(key)
|
87
120
|
end
|
88
121
|
end
|
89
122
|
list
|
90
123
|
end
|
91
124
|
|
92
|
-
def list_of_strings(name, values)
|
93
|
-
values.map do |value|
|
94
|
-
"#{name}=#{escape(value)}"
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
125
|
def escape(string)
|
99
126
|
Seahorse::Util.uri_escape(string)
|
100
127
|
end
|
101
|
-
|
102
128
|
end
|
103
129
|
end
|
104
130
|
end
|
@@ -20,7 +20,8 @@ module Aws
|
|
20
20
|
if event_stream?
|
21
21
|
data[@rules[:payload]] = parse_eventstream(body)
|
22
22
|
elsif streaming?
|
23
|
-
|
23
|
+
# empty blob payloads are omitted
|
24
|
+
data[@rules[:payload]] = body unless empty_blob_payload?(body)
|
24
25
|
elsif @rules[:payload]
|
25
26
|
data[@rules[:payload]] = parse(body.read, @rules[:payload_member])
|
26
27
|
elsif !@rules.shape.member_names.empty?
|
@@ -30,6 +31,19 @@ module Aws
|
|
30
31
|
|
31
32
|
private
|
32
33
|
|
34
|
+
def empty_blob_payload?(body)
|
35
|
+
true if non_streaming_blob_payload? && empty_body?(body)
|
36
|
+
end
|
37
|
+
|
38
|
+
def non_streaming_blob_payload?
|
39
|
+
@rules[:payload_member].shape.is_a?(BlobShape) &&
|
40
|
+
!@rules[:payload_member]['streaming']
|
41
|
+
end
|
42
|
+
|
43
|
+
def empty_body?(body)
|
44
|
+
body.respond_to?(:size) && body.size.zero?
|
45
|
+
end
|
46
|
+
|
33
47
|
def event_stream?
|
34
48
|
@rules[:payload] && @rules[:payload_member].eventstream
|
35
49
|
end
|