aws-sdk-core 3.191.6 → 3.192.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +25 -0
- data/VERSION +1 -1
- data/lib/aws-sdk-core/json/builder.rb +8 -1
- data/lib/aws-sdk-core/json/error_handler.rb +10 -3
- data/lib/aws-sdk-core/json/parser.rb +2 -1
- data/lib/aws-sdk-core/param_validator.rb +4 -0
- data/lib/aws-sdk-core/plugins/protocols/rest_json.rb +3 -16
- data/lib/aws-sdk-core/plugins/protocols/rest_xml.rb +1 -2
- data/lib/aws-sdk-core/plugins/request_compression.rb +1 -1
- data/lib/aws-sdk-core/query/param_builder.rb +2 -2
- data/lib/aws-sdk-core/rest/request/body.rb +32 -5
- data/lib/aws-sdk-core/rest/request/content_type.rb +51 -0
- data/lib/aws-sdk-core/rest/request/endpoint.rb +22 -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/util.rb +39 -0
- data/lib/aws-sdk-core/xml/builder.rb +17 -9
- data/lib/aws-sdk-core/xml/error_handler.rb +24 -8
- 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-sso/client.rb +1 -1
- data/lib/aws-sdk-sso.rb +1 -1
- data/lib/aws-sdk-ssooidc/client.rb +1 -1
- data/lib/aws-sdk-ssooidc.rb +1 -1
- data/lib/aws-sdk-sts/client.rb +1 -1
- data/lib/aws-sdk-sts/client_api.rb +8 -8
- data/lib/aws-sdk-sts.rb +1 -1
- data/lib/seahorse/model/shapes.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0d1127887a64dce6dfd29c25cf492e36bbfffc290a79f0bad1ee7c1d598f033d
|
4
|
+
data.tar.gz: c418f5ac7a761219bab8d022d03910b9646a7e929371d75a40e1b27e9b4d5771
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5c02ee8145d73c2e235ebfab5b6017219d767b6dca4160ae67476927cee7a8f0ad94752deb94930b168133cd3949eb110735baf5195a781fd842af218bee6a5c
|
7
|
+
data.tar.gz: fc3d6b824590a1f311ede6c5b5e0355dd9181b2d44e6ba2bf8414797fa98a053dc657aa929b2156520d99ac7b140270850c61a90a3c391aadc9bf3e83c98053e
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,31 @@
|
|
1
1
|
Unreleased Changes
|
2
2
|
------------------
|
3
3
|
|
4
|
+
3.192.0 (2024-04-16)
|
5
|
+
------------------
|
6
|
+
|
7
|
+
* Feature - Updated Aws::STS::Client with the latest API changes.
|
8
|
+
|
9
|
+
* Feature - Update serializing/deserializing for all protocols to align with Smithy protocol-tests.
|
10
|
+
* Issue - Allow `nil` values in lists and maps.
|
11
|
+
* Issue - Populate headers for XML and JSON error responses.
|
12
|
+
* Issue - Support fractional seconds when parsing `DateTime` timestamps.
|
13
|
+
* Issue - Correctly serialize flattened lists for Query protocol.
|
14
|
+
* Issue - Correctly serialize payload name in Rest-XML requests.
|
15
|
+
* Issue - Fix an issue where Rest-XML requests do not have a default `Content-Type` header applied.
|
16
|
+
* Issue - Apply appropriate `Content-Type` header for payloads in Rest services.
|
17
|
+
* Issue - Correctly serialize URI label bindings in Rest requests.
|
18
|
+
* Issue - Correctly serialize and parse header bindings in Rest services.
|
19
|
+
* Issue - Ensure that null and empty headers are not sent in Rest requests.
|
20
|
+
* Issue - Ensure keys in query maps do not override modeled keys in Rest requests.
|
21
|
+
* Issue - Ensure empty blob payloads are omitted in Rest requests.
|
22
|
+
* Issue - Support parsing of `NaN`, `Infinity` and `-Infinity` float values.
|
23
|
+
* Issue - Apply appropriate `xmlName` for flattened lists and maps in Rest-XML services.
|
24
|
+
* Issue - Handle serializing of different formats of `xmlNamespace` on shapes.
|
25
|
+
* Issue - Fix deserializing of an empty blob to produce an empty string.
|
26
|
+
* Issue - Fix deserializing an empty self-closed blob to produce an empty string.
|
27
|
+
* Issue - Support parsing of different formats of error data in Rest-XML services.
|
28
|
+
|
4
29
|
3.191.6 (2024-04-02)
|
5
30
|
------------------
|
6
31
|
* Issue - Performance optimization: ensure presence and order of instance variables in `PluginOptions` (#3002).
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.
|
1
|
+
3.192.0
|
@@ -8,7 +8,7 @@ module Aws
|
|
8
8
|
|
9
9
|
include Seahorse::Model::Shapes
|
10
10
|
|
11
|
-
def initialize(rules)
|
11
|
+
def initialize(rules, _options = {})
|
12
12
|
@rules = rules
|
13
13
|
end
|
14
14
|
|
@@ -20,6 +20,8 @@ module Aws
|
|
20
20
|
private
|
21
21
|
|
22
22
|
def structure(ref, values)
|
23
|
+
return nil if values.nil?
|
24
|
+
|
23
25
|
shape = ref.shape
|
24
26
|
values.each_pair.with_object({}) do |(key, value), data|
|
25
27
|
if shape.member?(key) && !value.nil?
|
@@ -31,11 +33,15 @@ module Aws
|
|
31
33
|
end
|
32
34
|
|
33
35
|
def list(ref, values)
|
36
|
+
return nil if values.nil?
|
37
|
+
|
34
38
|
member_ref = ref.shape.member
|
35
39
|
values.collect { |value| format(member_ref, value) }
|
36
40
|
end
|
37
41
|
|
38
42
|
def map(ref, values)
|
43
|
+
return nil if values.nil?
|
44
|
+
|
39
45
|
value_ref = ref.shape.value
|
40
46
|
values.each.with_object({}) do |(key, value), data|
|
41
47
|
data[key] = format(value_ref, value)
|
@@ -49,6 +55,7 @@ module Aws
|
|
49
55
|
when MapShape then map(ref, value)
|
50
56
|
when TimestampShape then timestamp(ref, value)
|
51
57
|
when BlobShape then encode(value)
|
58
|
+
when FloatShape then Util.serialize_number(value)
|
52
59
|
else value
|
53
60
|
end
|
54
61
|
end
|
@@ -71,14 +71,21 @@ module Aws
|
|
71
71
|
# some type(code) might contains invalid characters
|
72
72
|
# such as ':' (efs) etc
|
73
73
|
match = rule.shape.name == code.gsub(/[^^a-zA-Z0-9]/, '')
|
74
|
-
|
75
|
-
|
76
|
-
|
74
|
+
next unless match && rule.shape.members.any?
|
75
|
+
|
76
|
+
data = Parser.new(rule).parse(context.http_response.body_contents)
|
77
|
+
# errors support HTTP bindings
|
78
|
+
apply_error_headers(rule, context, data)
|
77
79
|
end
|
78
80
|
end
|
79
81
|
data
|
80
82
|
end
|
81
83
|
|
84
|
+
def apply_error_headers(rule, context, data)
|
85
|
+
headers = Aws::Rest::Response::Headers.new(rule)
|
86
|
+
headers.apply(context.http_response, data)
|
87
|
+
end
|
88
|
+
|
82
89
|
end
|
83
90
|
end
|
84
91
|
end
|
@@ -85,6 +85,7 @@ module Aws
|
|
85
85
|
when TimestampShape then time(value)
|
86
86
|
when BlobShape then Base64.decode64(value)
|
87
87
|
when BooleanShape then value.to_s == 'true'
|
88
|
+
when FloatShape then Util.deserialize_number(value)
|
88
89
|
else value
|
89
90
|
end
|
90
91
|
end
|
@@ -93,7 +94,7 @@ module Aws
|
|
93
94
|
# @param [String, Integer] value
|
94
95
|
# @return [Time]
|
95
96
|
def time(value)
|
96
|
-
value.is_a?(Numeric) ? Time.at(value) :
|
97
|
+
value.is_a?(Numeric) ? Time.at(value) : Aws::Util.deserialize_time(value)
|
97
98
|
end
|
98
99
|
|
99
100
|
def flattened_list?(shape)
|
@@ -107,6 +107,8 @@ module Aws
|
|
107
107
|
# validate members
|
108
108
|
member_ref = ref.shape.member
|
109
109
|
values.each.with_index do |value, index|
|
110
|
+
next unless value
|
111
|
+
|
110
112
|
shape(member_ref, value, errors, context + "[#{index}]")
|
111
113
|
end
|
112
114
|
end
|
@@ -122,6 +124,8 @@ module Aws
|
|
122
124
|
|
123
125
|
values.each do |key, value|
|
124
126
|
shape(key_ref, key, errors, "#{context} #{key.inspect} key")
|
127
|
+
next unless value
|
128
|
+
|
125
129
|
shape(value_ref, value, errors, context + "[#{key.inspect}]")
|
126
130
|
end
|
127
131
|
end
|
@@ -4,23 +4,10 @@ module Aws
|
|
4
4
|
module Plugins
|
5
5
|
module Protocols
|
6
6
|
class RestJson < Seahorse::Client::Plugin
|
7
|
-
|
8
|
-
class ContentTypeHandler < Seahorse::Client::Handler
|
9
|
-
def call(context)
|
10
|
-
body = context.http_request.body
|
11
|
-
# Rest::Handler will set a default JSON body, so size can be checked
|
12
|
-
# if this handler is run after serialization.
|
13
|
-
if !body.respond_to?(:size) ||
|
14
|
-
(body.respond_to?(:size) && body.size > 0)
|
15
|
-
context.http_request.headers['Content-Type'] ||=
|
16
|
-
'application/json'
|
17
|
-
end
|
18
|
-
@handler.call(context)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
7
|
handler(Rest::Handler)
|
23
|
-
|
8
|
+
# Rest::Handler will set a default JSON body, so size can be checked
|
9
|
+
# if this handler is run after serialization.
|
10
|
+
handler(Rest::ContentTypeHandler, priority: 30)
|
24
11
|
handler(Json::ErrorHandler, step: :sign)
|
25
12
|
end
|
26
13
|
|
@@ -104,7 +104,7 @@ and 10485780 bytes inclusive.
|
|
104
104
|
def update_content_encoding(encoding, context)
|
105
105
|
headers = context.http_request.headers
|
106
106
|
if headers['Content-Encoding']
|
107
|
-
headers['Content-Encoding'] +=
|
107
|
+
headers['Content-Encoding'] += ", #{encoding}"
|
108
108
|
else
|
109
109
|
headers['Content-Encoding'] = encoding
|
110
110
|
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)
|
@@ -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)
|
@@ -0,0 +1,51 @@
|
|
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
|
+
body = context.http_request.body
|
9
|
+
|
10
|
+
if (payload = context.operation.input[:payload_member])
|
11
|
+
case payload.shape
|
12
|
+
when Seahorse::Model::Shapes::BlobShape
|
13
|
+
context.http_request.headers['Content-Type'] ||=
|
14
|
+
'application/octet-stream'
|
15
|
+
when Seahorse::Model::Shapes::StringShape
|
16
|
+
context.http_request.headers['Content-Type'] ||=
|
17
|
+
'text/plain'
|
18
|
+
else
|
19
|
+
apply_default_content_type(context)
|
20
|
+
end
|
21
|
+
elsif !body.respond_to?(:size) || non_empty_body?(body)
|
22
|
+
apply_default_content_type(context)
|
23
|
+
end
|
24
|
+
|
25
|
+
@handler.call(context)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def non_empty_body?(body)
|
31
|
+
body.respond_to?(:size) && body.size.positive?
|
32
|
+
end
|
33
|
+
|
34
|
+
# content-type defaults as noted here:
|
35
|
+
# rest-json: https://smithy.io/2.0/aws/protocols/aws-restxml-protocol.html#content-type
|
36
|
+
# rest-xml: https://smithy.io/2.0/aws/protocols/aws-restxml-protocol.html#content-type
|
37
|
+
def apply_default_content_type(context)
|
38
|
+
protocol = context.config.api.metadata['protocol']
|
39
|
+
case protocol
|
40
|
+
when 'rest-json'
|
41
|
+
context.http_request.headers['Content-Type'] ||=
|
42
|
+
'application/json'
|
43
|
+
when 'rest-xml'
|
44
|
+
context.http_request.headers['Content-Type'] ||=
|
45
|
+
'application/xml'
|
46
|
+
else raise "Unsupported protocol #{protocol}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -30,7 +30,7 @@ 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{/$}, '') + @path_pattern.split('?')[0]
|
34
34
|
uri.path = path.gsub(/{.+?}/) do |placeholder|
|
35
35
|
param_value_for_placeholder(placeholder, params)
|
36
36
|
end
|
@@ -38,22 +38,40 @@ module Aws
|
|
38
38
|
|
39
39
|
def param_value_for_placeholder(placeholder, params)
|
40
40
|
name = param_name(placeholder)
|
41
|
-
|
41
|
+
param_shape = @rules.shape.member(name).shape
|
42
|
+
value =
|
43
|
+
case param_shape
|
44
|
+
when Seahorse::Model::Shapes::TimestampShape
|
45
|
+
timestamp(param_shape, params[name]).to_s
|
46
|
+
else
|
47
|
+
params[name].to_s
|
48
|
+
end
|
49
|
+
|
42
50
|
raise ArgumentError, ":#{name} must not be blank" if value.empty?
|
43
51
|
|
44
52
|
if placeholder.include?('+')
|
45
|
-
value.gsub(
|
53
|
+
value.gsub(%r{[^/]+}) { |v| escape(v) }
|
46
54
|
else
|
47
55
|
escape(value)
|
48
56
|
end
|
49
57
|
end
|
50
58
|
|
51
59
|
def param_name(placeholder)
|
52
|
-
location_name = placeholder.gsub(/[{}+]/,'')
|
60
|
+
location_name = placeholder.gsub(/[{}+]/, '')
|
53
61
|
param_name, _ = @rules.shape.member_by_location_name(location_name)
|
54
62
|
param_name
|
55
63
|
end
|
56
64
|
|
65
|
+
def timestamp(ref, value)
|
66
|
+
case ref['timestampFormat']
|
67
|
+
when 'unixTimestamp' then value.to_i
|
68
|
+
when 'rfc822' then value.utc.httpdate
|
69
|
+
else
|
70
|
+
# serializing as RFC 3399 date-time is the default
|
71
|
+
value.utc.iso8601
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
57
75
|
def apply_querystring_params(uri, params)
|
58
76
|
# collect params that are supposed to be part of the query string
|
59
77
|
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
|
@@ -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
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'strscan'
|
4
|
+
|
5
|
+
module Aws
|
6
|
+
module Rest
|
7
|
+
module Response
|
8
|
+
# @api private
|
9
|
+
module HeaderListParser
|
10
|
+
|
11
|
+
class << self
|
12
|
+
# parse a list of possibly quoted and escaped string values
|
13
|
+
# Follows:
|
14
|
+
# # [RFC-7230's specification of header values](https://datatracker.ietf.org/doc/html/rfc7230#section-3.2.6).
|
15
|
+
def parse_string_list(value)
|
16
|
+
buffer = StringScanner.new(value)
|
17
|
+
parsed = []
|
18
|
+
|
19
|
+
parsed << read_value(buffer) until buffer.eos?
|
20
|
+
|
21
|
+
parsed
|
22
|
+
end
|
23
|
+
|
24
|
+
def parse_timestamp_list(value, ref)
|
25
|
+
# timestamp lists use an http-date by default and are unescaped
|
26
|
+
# eg: Mon, 16 Dec 2019 23:48:18 GMT, Mon, 16 Dec 2019 23:48:18 GMT
|
27
|
+
case ref['timestampFormat'] || ref.shape['timestampFormat']
|
28
|
+
when 'unixTimestamp'
|
29
|
+
value.split(', ').map { |v| Time.at(v.to_f) }
|
30
|
+
when 'iso8601' then value.split(', ').map { |v| Time.parse(v) }
|
31
|
+
else
|
32
|
+
# header default to rfc822/http-date, which has a comma after day
|
33
|
+
value.split(',').each_slice(2).map { |v| Time.parse(v[0] + v[1])}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def read_value(buffer)
|
40
|
+
until buffer.eos?
|
41
|
+
case buffer.peek(1)
|
42
|
+
when ' ', "\t"
|
43
|
+
# drop leading whitespace
|
44
|
+
buffer.getch
|
45
|
+
next
|
46
|
+
when '"'
|
47
|
+
buffer.getch # drop the quote and advance
|
48
|
+
return read_quoted_value(buffer)
|
49
|
+
else
|
50
|
+
return read_unquoted_value(buffer)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
# buffer is only whitespace
|
54
|
+
nil
|
55
|
+
end
|
56
|
+
|
57
|
+
def read_unquoted_value(buffer)
|
58
|
+
# there cannot be any escaped values
|
59
|
+
value = buffer.scan_until(/,|$/)
|
60
|
+
# drop the comma if we matched it
|
61
|
+
buffer.matched == ',' ? value.chop : value
|
62
|
+
end
|
63
|
+
|
64
|
+
def read_quoted_value(buffer)
|
65
|
+
# scan until we have an unescaped double quote
|
66
|
+
value = buffer.scan_until(/[^\\]"/)
|
67
|
+
raise ArgumentError, 'Invalid String list: No closing quote found' unless value
|
68
|
+
|
69
|
+
# drop any remaining whitespace/commas
|
70
|
+
buffer.scan_until(/[\s,]*/)
|
71
|
+
# the last character will always be the closing quote.
|
72
|
+
# Add a starting quote and then unescape (undump)
|
73
|
+
"\"#{value}".undump
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'time'
|
4
4
|
require 'base64'
|
5
|
+
require_relative 'header_list_parser'
|
5
6
|
|
6
7
|
module Aws
|
7
8
|
module Rest
|
@@ -36,12 +37,16 @@ module Aws
|
|
36
37
|
def cast_value(ref, value)
|
37
38
|
value = extract_json_trait(value) if ref['jsonvalue']
|
38
39
|
case ref.shape
|
39
|
-
when StringShape then value
|
40
|
+
when StringShape then value.to_s
|
40
41
|
when IntegerShape then value.to_i
|
41
|
-
when FloatShape then value
|
42
|
+
when FloatShape then Util.deserialize_number(value)
|
42
43
|
when BooleanShape then value == 'true'
|
43
44
|
when ListShape then
|
44
|
-
|
45
|
+
case ref.shape.member.shape
|
46
|
+
when StringShape then HeaderListParser.parse_string_list(value)
|
47
|
+
when TimestampShape then HeaderListParser.parse_timestamp_list(value, ref.shape.member)
|
48
|
+
else value.split(', ').map { |v| cast_value(ref.shape.member, v) }
|
49
|
+
end
|
45
50
|
when TimestampShape
|
46
51
|
if value =~ /^\d+(\.\d*)/
|
47
52
|
Time.at(value.to_f)
|
data/lib/aws-sdk-core/rest.rb
CHANGED
@@ -6,6 +6,7 @@ require_relative 'rest/request/builder'
|
|
6
6
|
require_relative 'rest/request/endpoint'
|
7
7
|
require_relative 'rest/request/headers'
|
8
8
|
require_relative 'rest/request/querystring_builder'
|
9
|
+
require_relative 'rest/request/content_type'
|
9
10
|
require_relative 'rest/response/body'
|
10
11
|
require_relative 'rest/response/headers'
|
11
12
|
require_relative 'rest/response/parser'
|
data/lib/aws-sdk-core/util.rb
CHANGED
@@ -67,6 +67,45 @@ module Aws
|
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
|
+
# @param [Number] input
|
71
|
+
# @return [Number, String] The serialized number
|
72
|
+
def serialize_number(input)
|
73
|
+
if input == ::Float::INFINITY then 'Infinity'
|
74
|
+
elsif input == -::Float::INFINITY then '-Infinity'
|
75
|
+
elsif input&.nan? then 'NaN'
|
76
|
+
else
|
77
|
+
input
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# @param [String] str
|
82
|
+
# @return [Number] The input as a number
|
83
|
+
def deserialize_number(str)
|
84
|
+
case str
|
85
|
+
when 'Infinity' then ::Float::INFINITY
|
86
|
+
when '-Infinity' then -::Float::INFINITY
|
87
|
+
when 'NaN' then ::Float::NAN
|
88
|
+
when nil then nil
|
89
|
+
else str.to_f
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# @param [String, Integer] value
|
94
|
+
# @return [Time]
|
95
|
+
def deserialize_time(value)
|
96
|
+
case value
|
97
|
+
when nil then nil
|
98
|
+
when /^\d+$/ then Time.at(value.to_i)
|
99
|
+
else
|
100
|
+
begin
|
101
|
+
fractional_time = Time.parse(value).utc.to_f
|
102
|
+
Time.at(fractional_time)
|
103
|
+
rescue ArgumentError
|
104
|
+
raise "unhandled timestamp format `#{value}'"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
70
109
|
end
|
71
110
|
end
|
72
111
|
end
|
@@ -10,6 +10,8 @@ module Aws
|
|
10
10
|
|
11
11
|
def initialize(rules, options = {})
|
12
12
|
@rules = rules
|
13
|
+
@location_name =
|
14
|
+
options[:location_name].nil? ? @rules.location_name : options[:location_name]
|
13
15
|
@xml = options[:target] || []
|
14
16
|
indent = options[:indent] || ''
|
15
17
|
pad = options[:pad] || ''
|
@@ -17,7 +19,7 @@ module Aws
|
|
17
19
|
end
|
18
20
|
|
19
21
|
def to_xml(params)
|
20
|
-
structure(@
|
22
|
+
structure(@location_name, @rules, params)
|
21
23
|
@xml.join
|
22
24
|
end
|
23
25
|
alias serialize to_xml
|
@@ -50,7 +52,7 @@ module Aws
|
|
50
52
|
def list(name, ref, values)
|
51
53
|
if ref[:flattened] || ref.shape.flattened
|
52
54
|
values.each do |value|
|
53
|
-
member(
|
55
|
+
member(name, ref.shape.member, value)
|
54
56
|
end
|
55
57
|
else
|
56
58
|
node(name, ref) do
|
@@ -65,7 +67,7 @@ module Aws
|
|
65
67
|
def map(name, ref, hash)
|
66
68
|
key_ref = ref.shape.key
|
67
69
|
value_ref = ref.shape.value
|
68
|
-
if ref.shape.flattened
|
70
|
+
if ref[:flattened] || ref.shape.flattened
|
69
71
|
hash.each do |key, value|
|
70
72
|
node(name, ref) do
|
71
73
|
member(key_ref.location_name || 'key', key_ref, key)
|
@@ -75,7 +77,8 @@ module Aws
|
|
75
77
|
else
|
76
78
|
node(name, ref) do
|
77
79
|
hash.each do |key, value|
|
78
|
-
|
80
|
+
# Pass in a new ShapeRef to create an entry node
|
81
|
+
node('entry', ShapeRef.new) do
|
79
82
|
member(key_ref.location_name || 'key', key_ref, key)
|
80
83
|
member(value_ref.location_name || 'value', value_ref, value)
|
81
84
|
end
|
@@ -129,11 +132,16 @@ module Aws
|
|
129
132
|
end
|
130
133
|
|
131
134
|
def shape_attrs(ref)
|
132
|
-
if xmlns = ref['xmlNamespace']
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
135
|
+
if (xmlns = ref['xmlNamespace'])
|
136
|
+
case xmlns
|
137
|
+
when String
|
138
|
+
{ 'xmlns' => xmlns }
|
139
|
+
when Hash
|
140
|
+
if (prefix = xmlns['prefix'])
|
141
|
+
{ "xmlns:#{prefix}" => xmlns['uri'] }
|
142
|
+
else
|
143
|
+
{ 'xmlns' => xmlns['uri'] }
|
144
|
+
end
|
137
145
|
end
|
138
146
|
else
|
139
147
|
{}
|
@@ -26,8 +26,7 @@ module Aws
|
|
26
26
|
end
|
27
27
|
context[:request_id] = request_id(body)
|
28
28
|
errors_module = context.client.class.errors_module
|
29
|
-
|
30
|
-
error_class
|
29
|
+
errors_module.error_class(code).new(context, message, data)
|
31
30
|
end
|
32
31
|
|
33
32
|
def extract_error(body, context)
|
@@ -43,14 +42,15 @@ module Aws
|
|
43
42
|
data = EmptyStructure.new
|
44
43
|
if error_rules = context.operation.errors
|
45
44
|
error_rules.each do |rule|
|
46
|
-
#
|
47
|
-
#
|
48
|
-
# match modeled shape name
|
45
|
+
# query protocol may have custom error code
|
46
|
+
# reference: https://smithy.io/2.0/aws/protocols/aws-query-protocol.html#error-code-resolution
|
49
47
|
error_shape_code = rule.shape['error']['code'] if rule.shape['error']
|
50
48
|
match = (code == error_shape_code || code == rule.shape.name)
|
51
|
-
|
52
|
-
|
53
|
-
|
49
|
+
next unless match && rule.shape.members.any?
|
50
|
+
|
51
|
+
data = parse_error_data(rule, context.http_response.body_contents)
|
52
|
+
# supporting HTTP bindings
|
53
|
+
apply_error_headers(rule, context, data)
|
54
54
|
end
|
55
55
|
end
|
56
56
|
data
|
@@ -58,6 +58,22 @@ module Aws
|
|
58
58
|
EmptyStructure.new
|
59
59
|
end
|
60
60
|
|
61
|
+
def parse_error_data(rule, body)
|
62
|
+
# errors may nested under <Errors><Error>structure_data</Error></Errors>
|
63
|
+
# Or may be flat and under <Error>structure_data</Error>
|
64
|
+
body = body.tr("\n", '')
|
65
|
+
if matches = body.match(/<Error>(.+?)<\/Error>/)
|
66
|
+
Parser.new(rule).parse("<#{rule.shape.name}>#{matches[1]}</#{rule.shape.name}>")
|
67
|
+
else
|
68
|
+
EmptyStructure.new
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def apply_error_headers(rule, context, data)
|
73
|
+
headers = Aws::Rest::Response::Headers.new(rule)
|
74
|
+
headers.apply(context.http_response, data)
|
75
|
+
end
|
76
|
+
|
61
77
|
def error_code(body, context)
|
62
78
|
if matches = body.match(/<Code>(.+?)<\/Code>/)
|
63
79
|
remove_prefix(unescape(matches[1]), context)
|
@@ -138,11 +138,7 @@ module Aws
|
|
138
138
|
end
|
139
139
|
|
140
140
|
def xml_name(ref)
|
141
|
-
|
142
|
-
ref.shape.member.location_name || ref.location_name
|
143
|
-
else
|
144
|
-
ref.location_name
|
145
|
-
end
|
141
|
+
ref.location_name
|
146
142
|
end
|
147
143
|
|
148
144
|
def flattened_list?(ref)
|
@@ -266,7 +262,7 @@ module Aws
|
|
266
262
|
|
267
263
|
class BlobFrame < Frame
|
268
264
|
def result
|
269
|
-
@text.empty? ?
|
265
|
+
@text.empty? ? '' : Base64.decode64(@text.join)
|
270
266
|
end
|
271
267
|
end
|
272
268
|
|
@@ -278,7 +274,7 @@ module Aws
|
|
278
274
|
|
279
275
|
class FloatFrame < Frame
|
280
276
|
def result
|
281
|
-
@text.empty? ? nil : @text.join
|
277
|
+
@text.empty? ? nil : Aws::Util.deserialize_number(@text.join)
|
282
278
|
end
|
283
279
|
end
|
284
280
|
|
@@ -296,19 +292,7 @@ module Aws
|
|
296
292
|
|
297
293
|
class TimestampFrame < Frame
|
298
294
|
def result
|
299
|
-
@text.empty? ? nil :
|
300
|
-
end
|
301
|
-
def parse(value)
|
302
|
-
case value
|
303
|
-
when nil then nil
|
304
|
-
when /^\d+$/ then Time.at(value.to_i)
|
305
|
-
else
|
306
|
-
begin
|
307
|
-
Time.parse(value).utc
|
308
|
-
rescue ArgumentError
|
309
|
-
raise "unhandled timestamp format `#{value}'"
|
310
|
-
end
|
311
|
-
end
|
295
|
+
@text.empty? ? nil : Aws::Util.deserialize_time(@text.join)
|
312
296
|
end
|
313
297
|
end
|
314
298
|
|
@@ -24,6 +24,8 @@ module Aws
|
|
24
24
|
if name.to_s == 'encoding' && value.to_s == 'base64'
|
25
25
|
@frame = BlobFrame.new(name, @frame.parent, @frame.ref)
|
26
26
|
else
|
27
|
+
# don't try to parse shapes from xml namespace
|
28
|
+
return if name.to_s == 'xmlns'
|
27
29
|
start_element(name)
|
28
30
|
text(value)
|
29
31
|
end_element(name)
|
data/lib/aws-sdk-sso/client.rb
CHANGED
data/lib/aws-sdk-sso.rb
CHANGED
data/lib/aws-sdk-ssooidc.rb
CHANGED
data/lib/aws-sdk-sts/client.rb
CHANGED
@@ -2352,7 +2352,7 @@ module Aws::STS
|
|
2352
2352
|
params: params,
|
2353
2353
|
config: config)
|
2354
2354
|
context[:gem_name] = 'aws-sdk-core'
|
2355
|
-
context[:gem_version] = '3.
|
2355
|
+
context[:gem_version] = '3.192.0'
|
2356
2356
|
Seahorse::Client::Request.new(handlers, context)
|
2357
2357
|
end
|
2358
2358
|
|
@@ -24,7 +24,7 @@ module Aws::STS
|
|
24
24
|
Credentials = Shapes::StructureShape.new(name: 'Credentials')
|
25
25
|
DecodeAuthorizationMessageRequest = Shapes::StructureShape.new(name: 'DecodeAuthorizationMessageRequest')
|
26
26
|
DecodeAuthorizationMessageResponse = Shapes::StructureShape.new(name: 'DecodeAuthorizationMessageResponse')
|
27
|
-
ExpiredTokenException = Shapes::StructureShape.new(name: 'ExpiredTokenException')
|
27
|
+
ExpiredTokenException = Shapes::StructureShape.new(name: 'ExpiredTokenException', error: {"code"=>"ExpiredTokenException", "httpStatusCode"=>400, "senderFault"=>true})
|
28
28
|
FederatedUser = Shapes::StructureShape.new(name: 'FederatedUser')
|
29
29
|
GetAccessKeyInfoRequest = Shapes::StructureShape.new(name: 'GetAccessKeyInfoRequest')
|
30
30
|
GetAccessKeyInfoResponse = Shapes::StructureShape.new(name: 'GetAccessKeyInfoResponse')
|
@@ -34,18 +34,18 @@ module Aws::STS
|
|
34
34
|
GetFederationTokenResponse = Shapes::StructureShape.new(name: 'GetFederationTokenResponse')
|
35
35
|
GetSessionTokenRequest = Shapes::StructureShape.new(name: 'GetSessionTokenRequest')
|
36
36
|
GetSessionTokenResponse = Shapes::StructureShape.new(name: 'GetSessionTokenResponse')
|
37
|
-
IDPCommunicationErrorException = Shapes::StructureShape.new(name: 'IDPCommunicationErrorException')
|
38
|
-
IDPRejectedClaimException = Shapes::StructureShape.new(name: 'IDPRejectedClaimException')
|
39
|
-
InvalidAuthorizationMessageException = Shapes::StructureShape.new(name: 'InvalidAuthorizationMessageException')
|
40
|
-
InvalidIdentityTokenException = Shapes::StructureShape.new(name: 'InvalidIdentityTokenException')
|
37
|
+
IDPCommunicationErrorException = Shapes::StructureShape.new(name: 'IDPCommunicationErrorException', error: {"code"=>"IDPCommunicationError", "httpStatusCode"=>400, "senderFault"=>true})
|
38
|
+
IDPRejectedClaimException = Shapes::StructureShape.new(name: 'IDPRejectedClaimException', error: {"code"=>"IDPRejectedClaim", "httpStatusCode"=>403, "senderFault"=>true})
|
39
|
+
InvalidAuthorizationMessageException = Shapes::StructureShape.new(name: 'InvalidAuthorizationMessageException', error: {"code"=>"InvalidAuthorizationMessageException", "httpStatusCode"=>400, "senderFault"=>true})
|
40
|
+
InvalidIdentityTokenException = Shapes::StructureShape.new(name: 'InvalidIdentityTokenException', error: {"code"=>"InvalidIdentityToken", "httpStatusCode"=>400, "senderFault"=>true})
|
41
41
|
Issuer = Shapes::StringShape.new(name: 'Issuer')
|
42
|
-
MalformedPolicyDocumentException = Shapes::StructureShape.new(name: 'MalformedPolicyDocumentException')
|
42
|
+
MalformedPolicyDocumentException = Shapes::StructureShape.new(name: 'MalformedPolicyDocumentException', error: {"code"=>"MalformedPolicyDocument", "httpStatusCode"=>400, "senderFault"=>true})
|
43
43
|
NameQualifier = Shapes::StringShape.new(name: 'NameQualifier')
|
44
|
-
PackedPolicyTooLargeException = Shapes::StructureShape.new(name: 'PackedPolicyTooLargeException')
|
44
|
+
PackedPolicyTooLargeException = Shapes::StructureShape.new(name: 'PackedPolicyTooLargeException', error: {"code"=>"PackedPolicyTooLarge", "httpStatusCode"=>400, "senderFault"=>true})
|
45
45
|
PolicyDescriptorType = Shapes::StructureShape.new(name: 'PolicyDescriptorType')
|
46
46
|
ProvidedContext = Shapes::StructureShape.new(name: 'ProvidedContext')
|
47
47
|
ProvidedContextsListType = Shapes::ListShape.new(name: 'ProvidedContextsListType')
|
48
|
-
RegionDisabledException = Shapes::StructureShape.new(name: 'RegionDisabledException')
|
48
|
+
RegionDisabledException = Shapes::StructureShape.new(name: 'RegionDisabledException', error: {"code"=>"RegionDisabledException", "httpStatusCode"=>403, "senderFault"=>true})
|
49
49
|
SAMLAssertionType = Shapes::StringShape.new(name: 'SAMLAssertionType')
|
50
50
|
Subject = Shapes::StringShape.new(name: 'Subject')
|
51
51
|
SubjectType = Shapes::StringShape.new(name: 'SubjectType')
|
data/lib/aws-sdk-sts.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aws-sdk-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.192.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Amazon Web Services
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-04-
|
11
|
+
date: 2024-04-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: jmespath
|
@@ -212,10 +212,12 @@ files:
|
|
212
212
|
- lib/aws-sdk-core/rest/handler.rb
|
213
213
|
- lib/aws-sdk-core/rest/request/body.rb
|
214
214
|
- lib/aws-sdk-core/rest/request/builder.rb
|
215
|
+
- lib/aws-sdk-core/rest/request/content_type.rb
|
215
216
|
- lib/aws-sdk-core/rest/request/endpoint.rb
|
216
217
|
- lib/aws-sdk-core/rest/request/headers.rb
|
217
218
|
- lib/aws-sdk-core/rest/request/querystring_builder.rb
|
218
219
|
- lib/aws-sdk-core/rest/response/body.rb
|
220
|
+
- lib/aws-sdk-core/rest/response/header_list_parser.rb
|
219
221
|
- lib/aws-sdk-core/rest/response/headers.rb
|
220
222
|
- lib/aws-sdk-core/rest/response/parser.rb
|
221
223
|
- lib/aws-sdk-core/rest/response/status_code.rb
|