aws-sdk-core 3.171.1 → 3.234.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 +787 -0
- data/VERSION +1 -1
- data/lib/aws-defaults/default_configuration.rb +5 -6
- data/lib/aws-defaults.rb +4 -1
- data/lib/aws-sdk-core/arn.rb +1 -3
- data/lib/aws-sdk-core/assume_role_credentials.rb +21 -13
- data/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +16 -9
- 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/decoder.rb +308 -0
- data/lib/aws-sdk-core/cbor/encoder.rb +243 -0
- data/lib/aws-sdk-core/cbor.rb +53 -0
- data/lib/aws-sdk-core/client_side_monitoring.rb +9 -0
- data/lib/aws-sdk-core/client_stubs.rb +33 -55
- data/lib/aws-sdk-core/credential_provider.rb +8 -1
- data/lib/aws-sdk-core/credential_provider_chain.rb +74 -25
- data/lib/aws-sdk-core/credentials.rb +19 -6
- data/lib/aws-sdk-core/ec2_metadata.rb +1 -1
- data/lib/aws-sdk-core/ecs_credentials.rb +92 -24
- data/lib/aws-sdk-core/endpoints/endpoint.rb +3 -1
- data/lib/aws-sdk-core/endpoints/matchers.rb +21 -19
- data/lib/aws-sdk-core/endpoints.rb +106 -22
- data/lib/aws-sdk-core/error_handler.rb +46 -0
- data/lib/aws-sdk-core/errors.rb +14 -5
- data/lib/aws-sdk-core/event_emitter.rb +1 -17
- data/lib/aws-sdk-core/ini_parser.rb +7 -0
- data/lib/aws-sdk-core/instance_profile_credentials.rb +168 -155
- data/lib/aws-sdk-core/json/builder.rb +8 -1
- data/lib/aws-sdk-core/json/error_handler.rb +29 -13
- data/lib/aws-sdk-core/json/handler.rb +13 -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 +33 -3
- data/lib/aws-sdk-core/json.rb +43 -14
- data/lib/aws-sdk-core/log/formatter.rb +6 -0
- data/lib/aws-sdk-core/log/param_filter.rb +2 -2
- data/lib/aws-sdk-core/log/param_formatter.rb +7 -3
- data/lib/aws-sdk-core/log.rb +10 -0
- data/lib/aws-sdk-core/lru_cache.rb +75 -0
- data/lib/aws-sdk-core/pageable_response.rb +3 -1
- data/lib/aws-sdk-core/param_validator.rb +9 -4
- data/lib/aws-sdk-core/plugins/bearer_authorization.rb +2 -0
- data/lib/aws-sdk-core/plugins/checksum_algorithm.rb +348 -169
- data/lib/aws-sdk-core/plugins/client_metrics_plugin.rb +1 -1
- data/lib/aws-sdk-core/plugins/client_metrics_send_plugin.rb +14 -2
- data/lib/aws-sdk-core/plugins/credentials_configuration.rb +78 -56
- data/lib/aws-sdk-core/plugins/endpoint_pattern.rb +40 -32
- data/lib/aws-sdk-core/plugins/global_configuration.rb +8 -9
- data/lib/aws-sdk-core/plugins/http_checksum.rb +3 -8
- data/lib/aws-sdk-core/plugins/invocation_id.rb +1 -11
- data/lib/aws-sdk-core/plugins/logging.rb +2 -0
- 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/regional_endpoint.rb +162 -37
- data/lib/aws-sdk-core/plugins/request_compression.rb +226 -0
- data/lib/aws-sdk-core/plugins/retry_errors.rb +12 -3
- data/lib/aws-sdk-core/plugins/sign.rb +55 -33
- data/lib/aws-sdk-core/plugins/signature_v2.rb +2 -1
- data/lib/aws-sdk-core/plugins/signature_v4.rb +2 -1
- data/lib/aws-sdk-core/plugins/stub_responses.rb +59 -9
- data/lib/aws-sdk-core/plugins/telemetry.rb +75 -0
- data/lib/aws-sdk-core/plugins/transfer_encoding.rb +16 -9
- data/lib/aws-sdk-core/plugins/user_agent.rb +192 -14
- data/lib/aws-sdk-core/plugins.rb +39 -0
- data/lib/aws-sdk-core/process_credentials.rb +48 -29
- 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/refreshing_credentials.rb +20 -23
- data/lib/aws-sdk-core/resources.rb +8 -0
- 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 +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 +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/cbor_engine.rb +18 -0
- data/lib/aws-sdk-core/rpc_v2/content_type_handler.rb +47 -0
- data/lib/aws-sdk-core/rpc_v2/error_handler.rb +95 -0
- data/lib/aws-sdk-core/rpc_v2/handler.rb +79 -0
- data/lib/aws-sdk-core/rpc_v2/parser.rb +98 -0
- data/lib/aws-sdk-core/rpc_v2.rb +69 -0
- data/lib/aws-sdk-core/shared_config.rb +135 -39
- data/lib/aws-sdk-core/shared_credentials.rb +1 -7
- data/lib/aws-sdk-core/sso_credentials.rb +6 -3
- data/lib/aws-sdk-core/static_token_provider.rb +1 -2
- data/lib/aws-sdk-core/stubbing/protocols/ec2.rb +12 -11
- data/lib/aws-sdk-core/stubbing/protocols/json.rb +11 -10
- data/lib/aws-sdk-core/stubbing/protocols/query.rb +7 -6
- data/lib/aws-sdk-core/stubbing/protocols/rest.rb +2 -1
- data/lib/aws-sdk-core/stubbing/protocols/rest_json.rb +9 -8
- data/lib/aws-sdk-core/stubbing/protocols/rest_xml.rb +6 -5
- data/lib/aws-sdk-core/stubbing/protocols/rpc_v2.rb +39 -0
- data/lib/aws-sdk-core/stubbing/stub_data.rb +11 -0
- data/lib/aws-sdk-core/stubbing.rb +22 -0
- data/lib/aws-sdk-core/telemetry/base.rb +177 -0
- data/lib/aws-sdk-core/telemetry/no_op.rb +70 -0
- data/lib/aws-sdk-core/telemetry/otel.rb +235 -0
- data/lib/aws-sdk-core/telemetry/span_kind.rb +22 -0
- data/lib/aws-sdk-core/telemetry/span_status.rb +59 -0
- data/lib/aws-sdk-core/telemetry.rb +78 -0
- data/lib/aws-sdk-core/token.rb +3 -3
- data/lib/aws-sdk-core/token_provider.rb +4 -0
- data/lib/aws-sdk-core/token_provider_chain.rb +2 -6
- data/lib/aws-sdk-core/util.rb +41 -1
- data/lib/aws-sdk-core/waiters/poller.rb +12 -5
- data/lib/aws-sdk-core/xml/builder.rb +17 -9
- data/lib/aws-sdk-core/xml/error_handler.rb +35 -43
- 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 +82 -107
- data/lib/aws-sdk-sso/client.rb +205 -92
- data/lib/aws-sdk-sso/client_api.rb +7 -0
- data/lib/aws-sdk-sso/endpoint_parameters.rb +9 -6
- data/lib/aws-sdk-sso/endpoint_provider.rb +30 -28
- data/lib/aws-sdk-sso/endpoints.rb +3 -54
- data/lib/aws-sdk-sso/plugins/endpoints.rb +23 -22
- data/lib/aws-sdk-sso/types.rb +1 -0
- data/lib/aws-sdk-sso.rb +15 -11
- data/lib/aws-sdk-ssooidc/client.rb +625 -125
- data/lib/aws-sdk-ssooidc/client_api.rb +94 -1
- data/lib/aws-sdk-ssooidc/endpoint_parameters.rb +9 -6
- data/lib/aws-sdk-ssooidc/endpoint_provider.rb +30 -28
- data/lib/aws-sdk-ssooidc/endpoints.rb +3 -40
- data/lib/aws-sdk-ssooidc/errors.rb +62 -0
- data/lib/aws-sdk-ssooidc/plugins/endpoints.rb +23 -20
- data/lib/aws-sdk-ssooidc/types.rb +419 -53
- data/lib/aws-sdk-ssooidc.rb +15 -11
- data/lib/aws-sdk-sts/client.rb +526 -243
- data/lib/aws-sdk-sts/client_api.rb +48 -9
- data/lib/aws-sdk-sts/customizations.rb +5 -2
- data/lib/aws-sdk-sts/endpoint_parameters.rb +10 -9
- data/lib/aws-sdk-sts/endpoint_provider.rb +82 -84
- data/lib/aws-sdk-sts/endpoints.rb +3 -118
- data/lib/aws-sdk-sts/errors.rb +15 -0
- data/lib/aws-sdk-sts/plugins/endpoints.rb +23 -30
- data/lib/aws-sdk-sts/presigner.rb +3 -7
- data/lib/aws-sdk-sts/types.rb +217 -36
- data/lib/aws-sdk-sts.rb +15 -11
- data/lib/seahorse/client/async_base.rb +4 -5
- data/lib/seahorse/client/async_response.rb +19 -0
- data/lib/seahorse/client/base.rb +18 -21
- data/lib/seahorse/client/configuration.rb +0 -4
- data/lib/seahorse/client/h2/connection.rb +18 -28
- data/lib/seahorse/client/h2/handler.rb +14 -3
- data/lib/seahorse/client/handler.rb +1 -1
- data/lib/seahorse/client/http/response.rb +1 -1
- data/lib/seahorse/client/net_http/connection_pool.rb +15 -12
- data/lib/seahorse/client/net_http/handler.rb +21 -9
- data/lib/seahorse/client/net_http/patches.rb +1 -4
- data/lib/seahorse/client/networking_error.rb +1 -1
- data/lib/seahorse/client/plugin.rb +9 -0
- data/lib/seahorse/client/plugins/endpoint.rb +0 -1
- data/lib/seahorse/client/plugins/h2.rb +4 -4
- data/lib/seahorse/client/plugins/net_http.rb +57 -16
- data/lib/seahorse/client/plugins/request_callback.rb +31 -0
- data/lib/seahorse/client/request_context.rb +9 -2
- data/lib/seahorse/client/response.rb +8 -0
- data/lib/seahorse/model/operation.rb +3 -0
- data/lib/seahorse/model/shapes.rb +2 -2
- data/lib/seahorse/util.rb +2 -1
- data/sig/aws-sdk-core/async_client_stubs.rbs +21 -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/telemetry/base.rbs +46 -0
- data/sig/aws-sdk-core/telemetry/otel.rbs +22 -0
- data/sig/aws-sdk-core/telemetry/span_kind.rbs +15 -0
- data/sig/aws-sdk-core/telemetry/span_status.rbs +24 -0
- data/sig/aws-sdk-core/waiters/errors.rbs +20 -0
- data/sig/aws-sdk-core.rbs +7 -0
- data/sig/seahorse/client/async_base.rbs +18 -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 +106 -23
- /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
|
@@ -13,34 +13,131 @@ module Aws
|
|
|
13
13
|
begin
|
|
14
14
|
require 'aws-crt'
|
|
15
15
|
supported << 'CRC32C'
|
|
16
|
+
supported << 'CRC64NVME' if Aws::Crt::GEM_VERSION >= '0.3.0'
|
|
16
17
|
rescue LoadError
|
|
18
|
+
# Ignored
|
|
17
19
|
end
|
|
18
20
|
supported
|
|
19
21
|
end.freeze
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
CRT_ALGORITHMS = %w[CRC32C CRC64NVME].freeze
|
|
24
|
+
|
|
25
|
+
# Priority order of checksum algorithms to validate responses against.
|
|
26
|
+
# Remove any algorithms not supported by client (ie, depending on CRT availability).
|
|
27
|
+
# This list was chosen based on average performance.
|
|
28
|
+
CHECKSUM_ALGORITHM_PRIORITIES = %w[CRC32 CRC32C CRC64NVME SHA1 SHA256] & CLIENT_ALGORITHMS
|
|
24
29
|
|
|
25
30
|
# byte size of checksums, used in computing the trailer length
|
|
26
31
|
CHECKSUM_SIZE = {
|
|
27
|
-
'CRC32' =>
|
|
28
|
-
'CRC32C' =>
|
|
29
|
-
'
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
'CRC32' => 9,
|
|
33
|
+
'CRC32C' => 9,
|
|
34
|
+
'CRC64NVME' => 13,
|
|
35
|
+
# SHA functions need 1 byte padding because of how they are encoded
|
|
36
|
+
'SHA1' => 28 + 1,
|
|
37
|
+
'SHA256' => 44 + 1
|
|
38
|
+
}.freeze
|
|
39
|
+
|
|
40
|
+
DEFAULT_CHECKSUM = 'CRC32'
|
|
41
|
+
|
|
42
|
+
option(:request_checksum_calculation,
|
|
43
|
+
doc_default: 'when_supported',
|
|
44
|
+
doc_type: 'String',
|
|
45
|
+
docstring: <<~DOCS) do |cfg|
|
|
46
|
+
Determines when a checksum will be calculated for request payloads. Values are:
|
|
47
|
+
|
|
48
|
+
* `when_supported` - (default) When set, a checksum will be
|
|
49
|
+
calculated for all request payloads of operations modeled with the
|
|
50
|
+
`httpChecksum` trait where `requestChecksumRequired` is `true` and/or a
|
|
51
|
+
`requestAlgorithmMember` is modeled.
|
|
52
|
+
* `when_required` - When set, a checksum will only be calculated for
|
|
53
|
+
request payloads of operations modeled with the `httpChecksum` trait where
|
|
54
|
+
`requestChecksumRequired` is `true` or where a `requestAlgorithmMember`
|
|
55
|
+
is modeled and supplied.
|
|
56
|
+
DOCS
|
|
57
|
+
resolve_request_checksum_calculation(cfg)
|
|
58
|
+
end
|
|
32
59
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
60
|
+
option(:response_checksum_validation,
|
|
61
|
+
doc_default: 'when_supported',
|
|
62
|
+
doc_type: 'String',
|
|
63
|
+
docstring: <<~DOCS) do |cfg|
|
|
64
|
+
Determines when checksum validation will be performed on response payloads. Values are:
|
|
65
|
+
|
|
66
|
+
* `when_supported` - (default) When set, checksum validation is performed on all
|
|
67
|
+
response payloads of operations modeled with the `httpChecksum` trait where
|
|
68
|
+
`responseAlgorithms` is modeled, except when no modeled checksum algorithms
|
|
69
|
+
are supported.
|
|
70
|
+
* `when_required` - When set, checksum validation is not performed on
|
|
71
|
+
response payloads of operations unless the checksum algorithm is supported and
|
|
72
|
+
the `requestValidationModeMember` member is set to `ENABLED`.
|
|
73
|
+
DOCS
|
|
74
|
+
resolve_response_checksum_validation(cfg)
|
|
75
|
+
end
|
|
38
76
|
|
|
39
|
-
|
|
77
|
+
class << self
|
|
78
|
+
def digest_for_algorithm(algorithm)
|
|
79
|
+
case algorithm
|
|
80
|
+
when 'CRC32'
|
|
81
|
+
Digest.new(Zlib.method(:crc32), 'N')
|
|
82
|
+
when 'CRC32C'
|
|
83
|
+
Digest.new(Aws::Crt::Checksums.method(:crc32c), 'N')
|
|
84
|
+
when 'CRC64NVME'
|
|
85
|
+
Digest.new(Aws::Crt::Checksums.method(:crc64nvme), 'Q>')
|
|
86
|
+
when 'SHA1'
|
|
87
|
+
::Digest::SHA1.new
|
|
88
|
+
when 'SHA256'
|
|
89
|
+
::Digest::SHA256.new
|
|
90
|
+
else
|
|
91
|
+
raise ArgumentError,
|
|
92
|
+
"#{algorithm} is not a supported checksum algorithm."
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# The trailer size (in bytes) is the overhead (0, \r, \n) + the trailer
|
|
97
|
+
# name + the bytesize of the base64 encoded checksum.
|
|
98
|
+
def trailer_length(algorithm, location_name)
|
|
99
|
+
7 + location_name.size + CHECKSUM_SIZE[algorithm]
|
|
100
|
+
end
|
|
40
101
|
|
|
41
|
-
|
|
42
|
-
|
|
102
|
+
private
|
|
103
|
+
|
|
104
|
+
def resolve_request_checksum_calculation(cfg)
|
|
105
|
+
mode = ENV['AWS_REQUEST_CHECKSUM_CALCULATION'] ||
|
|
106
|
+
Aws.shared_config.request_checksum_calculation(profile: cfg.profile) ||
|
|
107
|
+
'when_supported'
|
|
108
|
+
mode = mode.downcase
|
|
109
|
+
unless %w[when_supported when_required].include?(mode)
|
|
110
|
+
raise ArgumentError,
|
|
111
|
+
'expected :request_checksum_calculation or' \
|
|
112
|
+
" ENV['AWS_REQUEST_CHECKSUM_CALCULATION'] to be " \
|
|
113
|
+
'`when_supported` or `when_required`.'
|
|
114
|
+
end
|
|
115
|
+
mode
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def resolve_response_checksum_validation(cfg)
|
|
119
|
+
mode = ENV['AWS_RESPONSE_CHECKSUM_VALIDATION'] ||
|
|
120
|
+
Aws.shared_config.response_checksum_validation(profile: cfg.profile) ||
|
|
121
|
+
'when_supported'
|
|
122
|
+
mode = mode.downcase
|
|
123
|
+
unless %w[when_supported when_required].include?(mode)
|
|
124
|
+
raise ArgumentError,
|
|
125
|
+
'expected :response_checksum_validation or' \
|
|
126
|
+
" ENV['AWS_RESPONSE_CHECKSUM_VALIDATION'] to be " \
|
|
127
|
+
'`when_supported` or `when_required`.'
|
|
128
|
+
end
|
|
129
|
+
mode
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# Interface for computing digests on request/response bodies
|
|
134
|
+
# which may be files, strings or IO like objects.
|
|
135
|
+
# Applies only to digest functions that produce 32 or 64 bit
|
|
136
|
+
# integer checksums (eg CRC32 or CRC64).
|
|
137
|
+
class Digest
|
|
138
|
+
def initialize(digest_fn, directive)
|
|
43
139
|
@digest_fn = digest_fn
|
|
140
|
+
@directive = directive
|
|
44
141
|
@value = 0
|
|
45
142
|
end
|
|
46
143
|
|
|
@@ -49,123 +146,237 @@ module Aws
|
|
|
49
146
|
end
|
|
50
147
|
|
|
51
148
|
def base64digest
|
|
52
|
-
Base64.encode64([@value].pack(
|
|
149
|
+
Base64.encode64([@value].pack(@directive)).chomp
|
|
53
150
|
end
|
|
54
151
|
end
|
|
55
152
|
|
|
56
153
|
def add_handlers(handlers, _config)
|
|
57
154
|
handlers.add(OptionHandler, step: :initialize)
|
|
58
|
-
#
|
|
59
|
-
# built but before it is signed
|
|
155
|
+
# Priority is set low to ensure the checksum is computed AFTER the
|
|
156
|
+
# request is built but before it is signed.
|
|
60
157
|
handlers.add(ChecksumHandler, priority: 15, step: :build)
|
|
61
158
|
end
|
|
62
159
|
|
|
63
|
-
private
|
|
64
|
-
|
|
65
|
-
def self.request_algorithm_selection(context)
|
|
66
|
-
return unless context.operation.http_checksum
|
|
67
|
-
|
|
68
|
-
input_member = context.operation.http_checksum['requestAlgorithmMember']
|
|
69
|
-
context.params[input_member.to_sym]&.upcase if input_member
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def self.request_validation_mode(context)
|
|
73
|
-
return unless context.operation.http_checksum
|
|
74
|
-
|
|
75
|
-
input_member = context.operation.http_checksum['requestValidationModeMember']
|
|
76
|
-
context.params[input_member.to_sym] if input_member
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
def self.operation_response_algorithms(context)
|
|
80
|
-
return unless context.operation.http_checksum
|
|
81
|
-
|
|
82
|
-
context.operation.http_checksum['responseAlgorithms']
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
# @api private
|
|
87
160
|
class OptionHandler < Seahorse::Client::Handler
|
|
88
161
|
def call(context)
|
|
89
162
|
context[:http_checksum] ||= {}
|
|
90
163
|
|
|
91
|
-
#
|
|
92
|
-
if
|
|
93
|
-
|
|
94
|
-
if (request_input == 'CRC32C')
|
|
95
|
-
raise ArgumentError, "CRC32C requires crt support - install the aws-crt gem for support."
|
|
96
|
-
else
|
|
97
|
-
raise ArgumentError, "#{request_input} is not a supported checksum algorithm."
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
# validate response configuration
|
|
103
|
-
if (ChecksumAlgorithm.request_validation_mode(context))
|
|
104
|
-
# Compute an ordered list as the union between priority supported and the
|
|
105
|
-
# operation's modeled response algorithms.
|
|
106
|
-
validation_list = CHECKSUM_ALGORITHM_PRIORITIES &
|
|
107
|
-
ChecksumAlgorithm.operation_response_algorithms(context)
|
|
108
|
-
context[:http_checksum][:validation_list] = validation_list
|
|
164
|
+
# Set validation mode to enabled when supported.
|
|
165
|
+
if context.config.response_checksum_validation == 'when_supported'
|
|
166
|
+
enable_request_validation_mode(context)
|
|
109
167
|
end
|
|
110
168
|
|
|
111
169
|
@handler.call(context)
|
|
112
170
|
end
|
|
171
|
+
|
|
172
|
+
private
|
|
173
|
+
|
|
174
|
+
def enable_request_validation_mode(context)
|
|
175
|
+
return unless context.operation.http_checksum
|
|
176
|
+
|
|
177
|
+
input_member = context.operation.http_checksum['requestValidationModeMember']
|
|
178
|
+
context.params[input_member.to_sym] ||= 'ENABLED' if input_member
|
|
179
|
+
end
|
|
113
180
|
end
|
|
114
181
|
|
|
115
|
-
# @api private
|
|
116
182
|
class ChecksumHandler < Seahorse::Client::Handler
|
|
117
|
-
|
|
118
183
|
def call(context)
|
|
184
|
+
algorithm = nil
|
|
119
185
|
if should_calculate_request_checksum?(context)
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
'name' => "x-amz-checksum-#{request_algorithm_input.downcase}"
|
|
186
|
+
algorithm = choose_request_algorithm!(context)
|
|
187
|
+
request_algorithm = {
|
|
188
|
+
algorithm: algorithm,
|
|
189
|
+
in: checksum_request_in(context),
|
|
190
|
+
name: "x-amz-checksum-#{algorithm.downcase}",
|
|
191
|
+
request_algorithm_header: request_algorithm_header(context)
|
|
127
192
|
}
|
|
128
|
-
|
|
129
|
-
calculate_request_checksum(context,
|
|
193
|
+
context[:http_checksum][:request_algorithm] = request_algorithm
|
|
194
|
+
calculate_request_checksum(context, request_algorithm)
|
|
130
195
|
end
|
|
131
196
|
|
|
132
197
|
if should_verify_response_checksum?(context)
|
|
133
198
|
add_verify_response_checksum_handlers(context)
|
|
134
199
|
end
|
|
135
200
|
|
|
136
|
-
@handler.call(context)
|
|
201
|
+
with_metrics(context.config, algorithm) { @handler.call(context) }
|
|
137
202
|
end
|
|
138
203
|
|
|
139
204
|
private
|
|
140
205
|
|
|
206
|
+
def with_metrics(config, algorithm, &block)
|
|
207
|
+
metrics = []
|
|
208
|
+
add_request_config_metric(config, metrics)
|
|
209
|
+
add_response_config_metric(config, metrics)
|
|
210
|
+
add_request_checksum_metrics(algorithm, metrics)
|
|
211
|
+
Aws::Plugins::UserAgent.metric(*metrics, &block)
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def add_request_config_metric(config, metrics)
|
|
215
|
+
case config.request_checksum_calculation
|
|
216
|
+
when 'when_supported'
|
|
217
|
+
metrics << 'FLEXIBLE_CHECKSUMS_REQ_WHEN_SUPPORTED'
|
|
218
|
+
when 'when_required'
|
|
219
|
+
metrics << 'FLEXIBLE_CHECKSUMS_REQ_WHEN_REQUIRED'
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def add_response_config_metric(config, metrics)
|
|
224
|
+
case config.response_checksum_validation
|
|
225
|
+
when 'when_supported'
|
|
226
|
+
metrics << 'FLEXIBLE_CHECKSUMS_RES_WHEN_SUPPORTED'
|
|
227
|
+
when 'when_required'
|
|
228
|
+
metrics << 'FLEXIBLE_CHECKSUMS_RES_WHEN_REQUIRED'
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
def add_request_checksum_metrics(algorithm, metrics)
|
|
233
|
+
case algorithm
|
|
234
|
+
when 'CRC32'
|
|
235
|
+
metrics << 'FLEXIBLE_CHECKSUMS_REQ_CRC32'
|
|
236
|
+
when 'CRC32C'
|
|
237
|
+
metrics << 'FLEXIBLE_CHECKSUMS_REQ_CRC32C'
|
|
238
|
+
when 'CRC64NVME'
|
|
239
|
+
metrics << 'FLEXIBLE_CHECKSUMS_REQ_CRC64'
|
|
240
|
+
when 'SHA1'
|
|
241
|
+
metrics << 'FLEXIBLE_CHECKSUMS_REQ_SHA1'
|
|
242
|
+
when 'SHA256'
|
|
243
|
+
metrics << 'FLEXIBLE_CHECKSUMS_REQ_SHA256'
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def request_algorithm_selection(context)
|
|
248
|
+
return unless context.operation.http_checksum
|
|
249
|
+
|
|
250
|
+
input_member = context.operation.http_checksum['requestAlgorithmMember']
|
|
251
|
+
|
|
252
|
+
context.params[input_member.to_sym] ||= DEFAULT_CHECKSUM if input_member
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
def request_algorithm_header(context)
|
|
256
|
+
input_member = context.operation.http_checksum['requestAlgorithmMember']
|
|
257
|
+
shape = context.operation.input.shape.member(input_member)
|
|
258
|
+
shape.location_name if shape && shape.location == 'header'
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def request_validation_mode(context)
|
|
262
|
+
return unless context.operation.http_checksum
|
|
263
|
+
|
|
264
|
+
input_member = context.operation.http_checksum['requestValidationModeMember']
|
|
265
|
+
context.params[input_member.to_sym] if input_member
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
def operation_response_algorithms(context)
|
|
269
|
+
return unless context.operation.http_checksum
|
|
270
|
+
|
|
271
|
+
context.operation.http_checksum['responseAlgorithms']
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
def checksum_provided_as_header?(headers)
|
|
275
|
+
headers.any? { |k, _| k.start_with?('x-amz-checksum-') }
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
# Determines whether a request checksum should be calculated.
|
|
279
|
+
# 1. **No existing checksum in header**: Skips if checksum header already present
|
|
280
|
+
# 2. **Operation support**: Considers model, client configuration and user input.
|
|
141
281
|
def should_calculate_request_checksum?(context)
|
|
142
|
-
context.
|
|
143
|
-
|
|
282
|
+
!checksum_provided_as_header?(context.http_request.headers) &&
|
|
283
|
+
checksum_applicable?(context)
|
|
144
284
|
end
|
|
145
285
|
|
|
146
|
-
|
|
147
|
-
|
|
286
|
+
# Checks if checksum calculation should proceed based on operation requirements and client settings.
|
|
287
|
+
# Returns true when any of these conditions are met:
|
|
288
|
+
# 1. http checksum's requestChecksumRequired is true
|
|
289
|
+
# 2. Config for request_checksum_calculation is "when_supported"
|
|
290
|
+
# 3. Config for request_checksum_calculation is "when_required" AND user provided checksum algorithm
|
|
291
|
+
def checksum_applicable?(context)
|
|
292
|
+
http_checksum = context.operation.http_checksum
|
|
293
|
+
return false unless http_checksum
|
|
294
|
+
|
|
295
|
+
return true if http_checksum['requestChecksumRequired']
|
|
296
|
+
|
|
297
|
+
return false unless (algorithm_member = http_checksum['requestAlgorithmMember'])
|
|
298
|
+
|
|
299
|
+
case context.config.request_checksum_calculation
|
|
300
|
+
when 'when_supported'
|
|
301
|
+
true
|
|
302
|
+
when 'when_required'
|
|
303
|
+
!context.params[algorithm_member.to_sym].nil?
|
|
304
|
+
else
|
|
305
|
+
false
|
|
306
|
+
end
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
def choose_request_algorithm!(context)
|
|
310
|
+
algorithm = request_algorithm_selection(context).upcase
|
|
311
|
+
return algorithm if CLIENT_ALGORITHMS.include?(algorithm)
|
|
312
|
+
|
|
313
|
+
if CRT_ALGORITHMS.include?(algorithm)
|
|
314
|
+
raise ArgumentError,
|
|
315
|
+
'CRC32C and CRC64NVME requires CRT support ' \
|
|
316
|
+
'- install the aws-crt gem'
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
raise ArgumentError,
|
|
320
|
+
"#{algorithm} is not a supported checksum algorithm."
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
def checksum_request_in(context)
|
|
324
|
+
if context.operation['unsignedPayload'] ||
|
|
325
|
+
context.operation['authtype'] == 'v4-unsigned-body'
|
|
326
|
+
'trailer'
|
|
327
|
+
else
|
|
328
|
+
'header'
|
|
329
|
+
end
|
|
148
330
|
end
|
|
149
331
|
|
|
150
332
|
def calculate_request_checksum(context, checksum_properties)
|
|
151
|
-
|
|
333
|
+
headers = context.http_request.headers
|
|
334
|
+
if (algorithm_header = checksum_properties[:request_algorithm_header])
|
|
335
|
+
headers[algorithm_header] = checksum_properties[:algorithm]
|
|
336
|
+
end
|
|
337
|
+
case checksum_properties[:in]
|
|
152
338
|
when 'header'
|
|
153
|
-
|
|
154
|
-
body = context.http_request.body_contents
|
|
155
|
-
if body
|
|
156
|
-
context.http_request.headers[header_name] ||=
|
|
157
|
-
ChecksumAlgorithm.calculate_checksum(checksum_properties['algorithm'], body)
|
|
158
|
-
end
|
|
339
|
+
apply_request_checksum(context, headers, checksum_properties)
|
|
159
340
|
when 'trailer'
|
|
160
|
-
apply_request_trailer_checksum(context, checksum_properties)
|
|
341
|
+
apply_request_trailer_checksum(context, headers, checksum_properties)
|
|
342
|
+
else
|
|
343
|
+
# nothing
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
def apply_request_checksum(context, headers, checksum_properties)
|
|
348
|
+
header_name = checksum_properties[:name]
|
|
349
|
+
body = context.http_request.body_contents
|
|
350
|
+
headers[header_name] = calculate_checksum(
|
|
351
|
+
checksum_properties[:algorithm],
|
|
352
|
+
body
|
|
353
|
+
)
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
def calculate_checksum(algorithm, body)
|
|
357
|
+
digest = ChecksumAlgorithm.digest_for_algorithm(algorithm)
|
|
358
|
+
if body.respond_to?(:read)
|
|
359
|
+
update_in_chunks(digest, body)
|
|
360
|
+
else
|
|
361
|
+
digest.update(body)
|
|
362
|
+
end
|
|
363
|
+
digest.base64digest
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
def update_in_chunks(digest, io)
|
|
367
|
+
loop do
|
|
368
|
+
chunk = io.read(CHUNK_SIZE)
|
|
369
|
+
break unless chunk
|
|
370
|
+
|
|
371
|
+
digest.update(chunk)
|
|
161
372
|
end
|
|
373
|
+
io.rewind
|
|
162
374
|
end
|
|
163
375
|
|
|
164
|
-
def apply_request_trailer_checksum(context, checksum_properties)
|
|
165
|
-
location_name = checksum_properties[
|
|
376
|
+
def apply_request_trailer_checksum(context, headers, checksum_properties)
|
|
377
|
+
location_name = checksum_properties[:name]
|
|
166
378
|
|
|
167
379
|
# set required headers
|
|
168
|
-
headers = context.http_request.headers
|
|
169
380
|
headers['Content-Encoding'] = 'aws-chunked'
|
|
170
381
|
headers['X-Amz-Content-Sha256'] = 'STREAMING-UNSIGNED-PAYLOAD-TRAILER'
|
|
171
382
|
headers['X-Amz-Trailer'] = location_name
|
|
@@ -174,120 +385,88 @@ module Aws
|
|
|
174
385
|
# to set the Content-Length header (set by content_length plugin).
|
|
175
386
|
# This means we cannot use Transfer-Encoding=chunked
|
|
176
387
|
|
|
177
|
-
|
|
388
|
+
unless context.http_request.body.respond_to?(:size)
|
|
178
389
|
raise Aws::Errors::ChecksumError, 'Could not determine length of the body'
|
|
179
390
|
end
|
|
180
391
|
headers['X-Amz-Decoded-Content-Length'] = context.http_request.body.size
|
|
181
392
|
|
|
182
393
|
context.http_request.body = AwsChunkedTrailerDigestIO.new(
|
|
183
394
|
context.http_request.body,
|
|
184
|
-
checksum_properties[
|
|
395
|
+
checksum_properties[:algorithm],
|
|
185
396
|
location_name
|
|
186
397
|
)
|
|
187
398
|
end
|
|
188
399
|
|
|
400
|
+
def should_verify_response_checksum?(context)
|
|
401
|
+
request_validation_mode(context) == 'ENABLED'
|
|
402
|
+
end
|
|
403
|
+
|
|
189
404
|
# Add events to the http_response to verify the checksum as its read
|
|
190
405
|
# This prevents the body from being read multiple times
|
|
191
406
|
# verification is done only once a successful response has completed
|
|
192
407
|
def add_verify_response_checksum_handlers(context)
|
|
193
|
-
|
|
194
|
-
checksum_context
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
expected = headers[header_name]
|
|
199
|
-
|
|
200
|
-
unless context[:http_checksum][:skip_on_suffix] && /-[\d]+$/.match(expected)
|
|
201
|
-
checksum_context[:algorithm] = algorithm
|
|
202
|
-
checksum_context[:header_name] = header_name
|
|
203
|
-
checksum_context[:digest] = ChecksumAlgorithm.digest_for_algorithm(algorithm)
|
|
204
|
-
checksum_context[:expected] = expected
|
|
205
|
-
end
|
|
206
|
-
end
|
|
207
|
-
end
|
|
408
|
+
checksum_context = {}
|
|
409
|
+
add_verify_response_headers_handler(context, checksum_context)
|
|
410
|
+
add_verify_response_data_handler(context, checksum_context)
|
|
411
|
+
add_verify_response_success_handler(context, checksum_context)
|
|
412
|
+
end
|
|
208
413
|
|
|
209
|
-
|
|
210
|
-
|
|
414
|
+
def add_verify_response_headers_handler(context, checksum_context)
|
|
415
|
+
validation_list = CHECKSUM_ALGORITHM_PRIORITIES &
|
|
416
|
+
operation_response_algorithms(context)
|
|
417
|
+
context[:http_checksum][:validation_list] = validation_list
|
|
418
|
+
|
|
419
|
+
context.http_response.on_headers do |_status, headers|
|
|
420
|
+
header_name, algorithm = response_header_to_verify(
|
|
421
|
+
headers,
|
|
422
|
+
validation_list
|
|
423
|
+
)
|
|
424
|
+
next unless header_name
|
|
425
|
+
|
|
426
|
+
expected = headers[header_name]
|
|
427
|
+
next if context[:http_checksum][:skip_on_suffix] && /-\d+$/.match(expected)
|
|
428
|
+
|
|
429
|
+
checksum_context[:algorithm] = algorithm
|
|
430
|
+
checksum_context[:header_name] = header_name
|
|
431
|
+
checksum_context[:digest] = ChecksumAlgorithm.digest_for_algorithm(algorithm)
|
|
432
|
+
checksum_context[:expected] = expected
|
|
211
433
|
end
|
|
434
|
+
end
|
|
212
435
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
436
|
+
def add_verify_response_data_handler(context, checksum_context)
|
|
437
|
+
context.http_response.on_data do |chunk|
|
|
438
|
+
checksum_context[:digest]&.update(chunk)
|
|
439
|
+
end
|
|
440
|
+
end
|
|
216
441
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
"computed: #{computed}, expected: #{checksum_context[:expected]}"
|
|
221
|
-
end
|
|
442
|
+
def add_verify_response_success_handler(context, checksum_context)
|
|
443
|
+
context.http_response.on_success do
|
|
444
|
+
next unless checksum_context[:digest]
|
|
222
445
|
|
|
446
|
+
computed = checksum_context[:digest].base64digest
|
|
447
|
+
if computed == checksum_context[:expected]
|
|
223
448
|
context[:http_checksum][:validated] = checksum_context[:algorithm]
|
|
449
|
+
else
|
|
450
|
+
raise Aws::Errors::ChecksumError,
|
|
451
|
+
"Checksum validation failed on #{checksum_context[:header_name]} "\
|
|
452
|
+
"computed: #{computed}, expected: #{checksum_context[:expected]}"
|
|
224
453
|
end
|
|
225
454
|
end
|
|
226
455
|
end
|
|
227
456
|
|
|
228
|
-
# returns nil if no headers to verify
|
|
229
457
|
def response_header_to_verify(headers, validation_list)
|
|
230
458
|
validation_list.each do |algorithm|
|
|
231
|
-
header_name = "x-amz-checksum-#{algorithm}"
|
|
459
|
+
header_name = "x-amz-checksum-#{algorithm.downcase}"
|
|
232
460
|
return [header_name, algorithm] if headers[header_name]
|
|
233
461
|
end
|
|
234
462
|
nil
|
|
235
463
|
end
|
|
236
|
-
|
|
237
|
-
# determine where (header vs trailer) a request checksum should be added
|
|
238
|
-
def checksum_request_in(context)
|
|
239
|
-
if context.operation['authtype'].eql?('v4-unsigned-body')
|
|
240
|
-
'trailer'
|
|
241
|
-
else
|
|
242
|
-
'header'
|
|
243
|
-
end
|
|
244
|
-
end
|
|
245
|
-
|
|
246
|
-
end
|
|
247
|
-
|
|
248
|
-
def self.calculate_checksum(algorithm, body)
|
|
249
|
-
digest = ChecksumAlgorithm.digest_for_algorithm(algorithm)
|
|
250
|
-
if body.respond_to?(:read)
|
|
251
|
-
ChecksumAlgorithm.update_in_chunks(digest, body)
|
|
252
|
-
else
|
|
253
|
-
digest.update(body)
|
|
254
|
-
end
|
|
255
|
-
digest.base64digest
|
|
256
|
-
end
|
|
257
|
-
|
|
258
|
-
def self.digest_for_algorithm(algorithm)
|
|
259
|
-
case algorithm
|
|
260
|
-
when 'CRC32'
|
|
261
|
-
Digest32.new(Zlib.method(:crc32))
|
|
262
|
-
when 'CRC32C'
|
|
263
|
-
# this will only be used if input algorithm is CRC32C AND client supports it (crt available)
|
|
264
|
-
Digest32.new(Aws::Crt::Checksums.method(:crc32c))
|
|
265
|
-
when 'SHA1'
|
|
266
|
-
Digest::SHA1.new
|
|
267
|
-
when 'SHA256'
|
|
268
|
-
Digest::SHA256.new
|
|
269
|
-
end
|
|
270
|
-
end
|
|
271
|
-
|
|
272
|
-
# The trailer size (in bytes) is the overhead + the trailer name +
|
|
273
|
-
# the length of the base64 encoded checksum
|
|
274
|
-
def self.trailer_length(algorithm, location_name)
|
|
275
|
-
CHECKSUM_SIZE[algorithm] + location_name.size
|
|
276
|
-
end
|
|
277
|
-
|
|
278
|
-
def self.update_in_chunks(digest, io)
|
|
279
|
-
loop do
|
|
280
|
-
chunk = io.read(CHUNK_SIZE)
|
|
281
|
-
break unless chunk
|
|
282
|
-
digest.update(chunk)
|
|
283
|
-
end
|
|
284
|
-
io.rewind
|
|
285
464
|
end
|
|
286
465
|
|
|
287
466
|
# Wrapper for request body that implements application-layer
|
|
288
467
|
# chunking with Digest computed on chunks + added as a trailer
|
|
289
468
|
class AwsChunkedTrailerDigestIO
|
|
290
|
-
CHUNK_SIZE =
|
|
469
|
+
CHUNK_SIZE = 16_384
|
|
291
470
|
|
|
292
471
|
def initialize(io, algorithm, location_name)
|
|
293
472
|
@io = io
|
|
@@ -314,7 +493,7 @@ module Aws
|
|
|
314
493
|
@io.rewind
|
|
315
494
|
end
|
|
316
495
|
|
|
317
|
-
def read(length, buf)
|
|
496
|
+
def read(length, buf = nil)
|
|
318
497
|
# account for possible leftover bytes at the end, if we have trailer bytes, send them
|
|
319
498
|
if @trailer_io
|
|
320
499
|
return @trailer_io.read(length, buf)
|
|
@@ -328,7 +507,7 @@ module Aws
|
|
|
328
507
|
else
|
|
329
508
|
trailers = {}
|
|
330
509
|
trailers[@location_name] = @digest.base64digest
|
|
331
|
-
trailers = trailers.map { |k,v| "#{k}:#{v}"}.join("\r\n")
|
|
510
|
+
trailers = trailers.map { |k,v| "#{k}:#{v}" }.join("\r\n")
|
|
332
511
|
@trailer_io = StringIO.new("0\r\n#{trailers}\r\n\r\n")
|
|
333
512
|
chunk = @trailer_io.read(length, buf)
|
|
334
513
|
end
|
|
@@ -40,6 +40,7 @@ side monitoring agent is running on, where client metrics will be published via
|
|
|
40
40
|
option(:client_side_monitoring_publisher,
|
|
41
41
|
default: ClientSideMonitoring::Publisher,
|
|
42
42
|
doc_type: Aws::ClientSideMonitoring::Publisher,
|
|
43
|
+
rbs_type: 'untyped',
|
|
43
44
|
docstring: <<-DOCS) do |cfg|
|
|
44
45
|
Allows you to provide a custom client-side monitoring publisher class. By default,
|
|
45
46
|
will use the Client Side Monitoring Agent Publisher.
|
|
@@ -179,7 +180,6 @@ all generated client side metrics. Defaults to an empty string.
|
|
|
179
180
|
complete_opts = {
|
|
180
181
|
latency: end_time - start_time,
|
|
181
182
|
attempt_count: context.retries + 1,
|
|
182
|
-
user_agent: context.http_request.headers["user-agent"],
|
|
183
183
|
final_error_retryable: final_error_retryable,
|
|
184
184
|
final_http_status_code: context.http_response.status_code,
|
|
185
185
|
final_aws_exception: final_aws_exception,
|