aws-sdk-core 3.0.0 → 3.129.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +1287 -0
- data/LICENSE.txt +202 -0
- data/VERSION +1 -1
- data/ca-bundle.crt +3615 -3541
- 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 +92 -0
- data/lib/aws-sdk-core/arn_parser.rb +40 -0
- data/lib/aws-sdk-core/assume_role_credentials.rb +20 -0
- data/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +109 -0
- data/lib/aws-sdk-core/async_client_stubs.rb +82 -0
- data/lib/aws-sdk-core/binary/decode_handler.rb +58 -0
- data/lib/aws-sdk-core/binary/encode_handler.rb +34 -0
- data/lib/aws-sdk-core/binary/event_builder.rb +124 -0
- data/lib/aws-sdk-core/binary/event_parser.rb +136 -0
- data/lib/aws-sdk-core/binary/event_stream_decoder.rb +64 -0
- data/lib/aws-sdk-core/binary/event_stream_encoder.rb +55 -0
- data/lib/aws-sdk-core/binary.rb +8 -0
- data/lib/aws-sdk-core/client_side_monitoring/publisher.rb +51 -0
- data/lib/aws-sdk-core/client_side_monitoring/request_metrics.rb +199 -0
- data/lib/aws-sdk-core/client_stubs.rb +55 -10
- data/lib/aws-sdk-core/credential_provider.rb +1 -30
- data/lib/aws-sdk-core/credential_provider_chain.rb +111 -33
- data/lib/aws-sdk-core/credentials.rb +2 -0
- data/lib/aws-sdk-core/deprecations.rb +17 -11
- data/lib/aws-sdk-core/eager_loader.rb +2 -0
- data/lib/aws-sdk-core/ec2_metadata.rb +238 -0
- data/lib/aws-sdk-core/ecs_credentials.rb +20 -11
- data/lib/aws-sdk-core/endpoint_cache.rb +193 -0
- data/lib/aws-sdk-core/errors.rb +210 -12
- data/lib/aws-sdk-core/event_emitter.rb +64 -0
- data/lib/aws-sdk-core/ini_parser.rb +2 -0
- data/lib/aws-sdk-core/instance_profile_credentials.rb +237 -45
- data/lib/aws-sdk-core/json/builder.rb +6 -2
- data/lib/aws-sdk-core/json/error_handler.rb +21 -2
- data/lib/aws-sdk-core/json/handler.rb +21 -1
- data/lib/aws-sdk-core/json/json_engine.rb +12 -8
- data/lib/aws-sdk-core/json/oj_engine.rb +35 -6
- data/lib/aws-sdk-core/json/parser.rb +10 -0
- data/lib/aws-sdk-core/json.rb +11 -28
- data/lib/aws-sdk-core/log/formatter.rb +16 -4
- data/lib/aws-sdk-core/log/handler.rb +2 -0
- data/lib/aws-sdk-core/log/param_filter.rb +38 -13
- data/lib/aws-sdk-core/log/param_formatter.rb +2 -0
- data/lib/aws-sdk-core/pageable_response.rb +111 -47
- data/lib/aws-sdk-core/pager.rb +5 -0
- data/lib/aws-sdk-core/param_converter.rb +2 -0
- data/lib/aws-sdk-core/param_validator.rb +99 -22
- data/lib/aws-sdk-core/plugins/api_key.rb +56 -0
- data/lib/aws-sdk-core/plugins/apig_authorizer_token.rb +32 -0
- data/lib/aws-sdk-core/plugins/apig_credentials_configuration.rb +36 -0
- data/lib/aws-sdk-core/plugins/apig_user_agent.rb +39 -0
- data/lib/aws-sdk-core/plugins/checksum_algorithm.rb +340 -0
- data/lib/aws-sdk-core/plugins/client_metrics_plugin.rb +283 -0
- data/lib/aws-sdk-core/plugins/client_metrics_send_plugin.rb +86 -0
- data/lib/aws-sdk-core/plugins/credentials_configuration.rb +26 -7
- data/lib/aws-sdk-core/plugins/defaults_mode.rb +40 -0
- data/lib/aws-sdk-core/plugins/endpoint_discovery.rb +168 -0
- data/lib/aws-sdk-core/plugins/endpoint_pattern.rb +65 -0
- data/lib/aws-sdk-core/plugins/event_stream_configuration.rb +32 -0
- data/lib/aws-sdk-core/plugins/global_configuration.rb +2 -0
- data/lib/aws-sdk-core/plugins/helpful_socket_errors.rb +2 -0
- data/lib/aws-sdk-core/plugins/http_checksum.rb +64 -0
- data/lib/aws-sdk-core/plugins/idempotency_token.rb +2 -0
- data/lib/aws-sdk-core/plugins/invocation_id.rb +35 -0
- data/lib/aws-sdk-core/plugins/jsonvalue_converter.rb +2 -0
- data/lib/aws-sdk-core/plugins/logging.rb +2 -0
- data/lib/aws-sdk-core/plugins/param_converter.rb +2 -0
- data/lib/aws-sdk-core/plugins/param_validator.rb +2 -0
- data/lib/aws-sdk-core/plugins/protocols/api_gateway.rb +29 -0
- data/lib/aws-sdk-core/plugins/protocols/ec2.rb +2 -0
- data/lib/aws-sdk-core/plugins/protocols/json_rpc.rb +2 -0
- data/lib/aws-sdk-core/plugins/protocols/query.rb +2 -0
- data/lib/aws-sdk-core/plugins/protocols/rest_json.rb +18 -1
- data/lib/aws-sdk-core/plugins/protocols/rest_xml.rb +2 -0
- data/lib/aws-sdk-core/plugins/recursion_detection.rb +27 -0
- data/lib/aws-sdk-core/plugins/regional_endpoint.rb +76 -16
- data/lib/aws-sdk-core/plugins/response_paging.rb +3 -1
- data/lib/aws-sdk-core/plugins/retries/client_rate_limiter.rb +139 -0
- data/lib/aws-sdk-core/plugins/retries/clock_skew.rb +100 -0
- data/lib/aws-sdk-core/plugins/retries/error_inspector.rb +146 -0
- data/lib/aws-sdk-core/plugins/retries/retry_quota.rb +59 -0
- data/lib/aws-sdk-core/plugins/retry_errors.rb +334 -78
- data/lib/aws-sdk-core/plugins/signature_v2.rb +2 -0
- data/lib/aws-sdk-core/plugins/signature_v4.rb +33 -28
- data/lib/aws-sdk-core/plugins/stub_responses.rb +31 -7
- data/lib/aws-sdk-core/plugins/transfer_encoding.rb +53 -0
- data/lib/aws-sdk-core/plugins/user_agent.rb +9 -5
- data/lib/aws-sdk-core/process_credentials.rb +81 -0
- data/lib/aws-sdk-core/query/ec2_param_builder.rb +11 -3
- data/lib/aws-sdk-core/query/handler.rb +8 -1
- data/lib/aws-sdk-core/query/param.rb +2 -0
- data/lib/aws-sdk-core/query/param_builder.rb +11 -3
- data/lib/aws-sdk-core/query/param_list.rb +2 -0
- data/lib/aws-sdk-core/query.rb +2 -0
- data/lib/aws-sdk-core/refreshing_credentials.rb +16 -3
- data/lib/aws-sdk-core/resources/collection.rb +7 -5
- data/lib/aws-sdk-core/rest/handler.rb +2 -0
- data/lib/aws-sdk-core/rest/request/body.rb +21 -1
- data/lib/aws-sdk-core/rest/request/builder.rb +4 -1
- data/lib/aws-sdk-core/rest/request/endpoint.rb +13 -6
- data/lib/aws-sdk-core/rest/request/headers.rb +30 -6
- data/lib/aws-sdk-core/rest/request/querystring_builder.rb +17 -2
- data/lib/aws-sdk-core/rest/response/body.rb +16 -1
- data/lib/aws-sdk-core/rest/response/headers.rb +8 -3
- data/lib/aws-sdk-core/rest/response/parser.rb +7 -1
- data/lib/aws-sdk-core/rest/response/status_code.rb +2 -0
- data/lib/aws-sdk-core/rest.rb +2 -0
- data/lib/aws-sdk-core/shared_config.rb +204 -68
- data/lib/aws-sdk-core/shared_credentials.rb +9 -1
- data/lib/aws-sdk-core/sso_credentials.rb +136 -0
- data/lib/aws-sdk-core/structure.rb +18 -3
- data/lib/aws-sdk-core/stubbing/data_applicator.rb +2 -0
- data/lib/aws-sdk-core/stubbing/empty_stub.rb +6 -1
- data/lib/aws-sdk-core/stubbing/protocols/api_gateway.rb +10 -0
- data/lib/aws-sdk-core/stubbing/protocols/ec2.rb +2 -0
- data/lib/aws-sdk-core/stubbing/protocols/json.rb +3 -1
- data/lib/aws-sdk-core/stubbing/protocols/query.rb +4 -2
- data/lib/aws-sdk-core/stubbing/protocols/rest.rb +120 -2
- data/lib/aws-sdk-core/stubbing/protocols/rest_json.rb +8 -2
- data/lib/aws-sdk-core/stubbing/protocols/rest_xml.rb +11 -7
- data/lib/aws-sdk-core/stubbing/stub_data.rb +15 -4
- data/lib/aws-sdk-core/stubbing/xml_error.rb +2 -0
- data/lib/aws-sdk-core/type_builder.rb +2 -0
- data/lib/aws-sdk-core/util.rb +34 -1
- data/lib/aws-sdk-core/waiters/errors.rb +2 -0
- data/lib/aws-sdk-core/waiters/poller.rb +2 -0
- data/lib/aws-sdk-core/waiters/waiter.rb +4 -2
- data/lib/aws-sdk-core/waiters.rb +2 -0
- data/lib/aws-sdk-core/xml/builder.rb +14 -6
- data/lib/aws-sdk-core/xml/default_list.rb +2 -0
- data/lib/aws-sdk-core/xml/default_map.rb +2 -0
- data/lib/aws-sdk-core/xml/doc_builder.rb +15 -4
- data/lib/aws-sdk-core/xml/error_handler.rb +29 -4
- data/lib/aws-sdk-core/xml/parser/engines/libxml.rb +2 -0
- data/lib/aws-sdk-core/xml/parser/engines/nokogiri.rb +2 -0
- data/lib/aws-sdk-core/xml/parser/engines/oga.rb +2 -0
- data/lib/aws-sdk-core/xml/parser/engines/ox.rb +3 -1
- data/lib/aws-sdk-core/xml/parser/engines/rexml.rb +4 -1
- data/lib/aws-sdk-core/xml/parser/frame.rb +30 -5
- data/lib/aws-sdk-core/xml/parser/parsing_error.rb +2 -0
- data/lib/aws-sdk-core/xml/parser/stack.rb +2 -0
- data/lib/aws-sdk-core/xml/parser.rb +7 -0
- data/lib/aws-sdk-core/xml.rb +2 -0
- data/lib/aws-sdk-core.rb +39 -5
- data/lib/aws-sdk-sso/client.rb +570 -0
- data/lib/aws-sdk-sso/client_api.rb +190 -0
- data/lib/aws-sdk-sso/customizations.rb +1 -0
- data/lib/aws-sdk-sso/errors.rb +102 -0
- data/lib/aws-sdk-sso/resource.rb +26 -0
- data/lib/aws-sdk-sso/types.rb +352 -0
- data/lib/aws-sdk-sso.rb +55 -0
- data/lib/aws-sdk-sts/client.rb +1474 -598
- data/lib/aws-sdk-sts/client_api.rb +81 -1
- data/lib/aws-sdk-sts/customizations.rb +4 -0
- data/lib/aws-sdk-sts/errors.rb +153 -1
- data/lib/aws-sdk-sts/plugins/sts_regional_endpoints.rb +38 -0
- data/lib/aws-sdk-sts/presigner.rb +75 -0
- data/lib/aws-sdk-sts/resource.rb +4 -1
- data/lib/aws-sdk-sts/types.rb +1005 -251
- data/lib/aws-sdk-sts.rb +16 -6
- data/lib/seahorse/client/async_base.rb +52 -0
- data/lib/seahorse/client/async_response.rb +64 -0
- data/lib/seahorse/client/base.rb +7 -2
- data/lib/seahorse/client/block_io.rb +6 -2
- data/lib/seahorse/client/configuration.rb +16 -2
- data/lib/seahorse/client/events.rb +3 -1
- data/lib/seahorse/client/h2/connection.rb +250 -0
- data/lib/seahorse/client/h2/handler.rb +152 -0
- data/lib/seahorse/client/handler.rb +2 -0
- data/lib/seahorse/client/handler_builder.rb +2 -0
- data/lib/seahorse/client/handler_list.rb +2 -0
- data/lib/seahorse/client/handler_list_entry.rb +6 -4
- data/lib/seahorse/client/http/async_response.rb +44 -0
- data/lib/seahorse/client/http/headers.rb +2 -0
- data/lib/seahorse/client/http/request.rb +5 -3
- data/lib/seahorse/client/http/response.rb +18 -11
- data/lib/seahorse/client/logging/formatter.rb +6 -2
- data/lib/seahorse/client/logging/handler.rb +2 -0
- data/lib/seahorse/client/managed_file.rb +2 -0
- data/lib/seahorse/client/net_http/connection_pool.rb +43 -27
- data/lib/seahorse/client/net_http/handler.rb +27 -7
- data/lib/seahorse/client/net_http/patches.rb +17 -79
- data/lib/seahorse/client/networking_error.rb +30 -0
- data/lib/seahorse/client/plugin.rb +10 -7
- data/lib/seahorse/client/plugin_list.rb +2 -0
- data/lib/seahorse/client/plugins/content_length.rb +14 -3
- data/lib/seahorse/client/plugins/endpoint.rb +4 -2
- data/lib/seahorse/client/plugins/h2.rb +69 -0
- data/lib/seahorse/client/plugins/logging.rb +2 -0
- data/lib/seahorse/client/plugins/net_http.rb +39 -3
- data/lib/seahorse/client/plugins/operation_methods.rb +2 -0
- data/lib/seahorse/client/plugins/raise_response_errors.rb +2 -0
- data/lib/seahorse/client/plugins/request_callback.rb +110 -0
- data/lib/seahorse/client/plugins/response_target.rb +26 -10
- data/lib/seahorse/client/request.rb +2 -0
- data/lib/seahorse/client/request_context.rb +7 -0
- data/lib/seahorse/client/response.rb +5 -5
- data/lib/seahorse/model/api.rb +39 -0
- data/lib/seahorse/model/authorizer.rb +23 -0
- data/lib/seahorse/model/operation.rb +28 -0
- data/lib/seahorse/model/shapes.rb +53 -0
- data/lib/seahorse/util.rb +9 -2
- data/lib/seahorse/version.rb +2 -0
- data/lib/seahorse.rb +13 -0
- metadata +99 -12
- data/lib/aws-sdk-core/version.rb +0 -3
data/lib/aws-sdk-sts.rb
CHANGED
@@ -1,11 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# WARNING ABOUT GENERATED CODE
|
2
4
|
#
|
3
5
|
# This file is generated. See the contributing guide for more information:
|
4
|
-
# https://github.com/aws/aws-sdk-ruby/blob/
|
6
|
+
# https://github.com/aws/aws-sdk-ruby/blob/version-3/CONTRIBUTING.md
|
5
7
|
#
|
6
8
|
# WARNING ABOUT GENERATED CODE
|
7
9
|
|
8
10
|
|
11
|
+
unless Module.const_defined?(:Aws)
|
12
|
+
require 'aws-sdk-core'
|
13
|
+
require 'aws-sigv4'
|
14
|
+
end
|
15
|
+
|
9
16
|
require_relative 'aws-sdk-sts/types'
|
10
17
|
require_relative 'aws-sdk-sts/client_api'
|
11
18
|
require_relative 'aws-sdk-sts/client'
|
@@ -22,24 +29,27 @@ require_relative 'aws-sdk-sts/customizations'
|
|
22
29
|
# methods each accept a hash of request parameters and return a response
|
23
30
|
# structure.
|
24
31
|
#
|
32
|
+
# sts = Aws::STS::Client.new
|
33
|
+
# resp = sts.assume_role(params)
|
34
|
+
#
|
25
35
|
# See {Client} for more information.
|
26
36
|
#
|
27
37
|
# # Errors
|
28
38
|
#
|
29
|
-
# Errors returned from AWS Security Token Service
|
30
|
-
# extend {Errors::ServiceError}.
|
39
|
+
# Errors returned from AWS Security Token Service are defined in the
|
40
|
+
# {Errors} module and all extend {Errors::ServiceError}.
|
31
41
|
#
|
32
42
|
# begin
|
33
43
|
# # do stuff
|
34
44
|
# rescue Aws::STS::Errors::ServiceError
|
35
|
-
# # rescues all
|
45
|
+
# # rescues all AWS Security Token Service API errors
|
36
46
|
# end
|
37
47
|
#
|
38
48
|
# See {Errors} for more information.
|
39
49
|
#
|
40
|
-
#
|
50
|
+
# @!group service
|
41
51
|
module Aws::STS
|
42
52
|
|
43
|
-
GEM_VERSION = '3.
|
53
|
+
GEM_VERSION = '3.129.1'
|
44
54
|
|
45
55
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Seahorse
|
4
|
+
module Client
|
5
|
+
class AsyncBase < Seahorse::Client::Base
|
6
|
+
|
7
|
+
# default H2 plugins
|
8
|
+
@plugins = PluginList.new([
|
9
|
+
Plugins::Endpoint,
|
10
|
+
Plugins::H2,
|
11
|
+
Plugins::ResponseTarget
|
12
|
+
])
|
13
|
+
|
14
|
+
def initialize(plugins, options)
|
15
|
+
super
|
16
|
+
@connection = H2::Connection.new(options)
|
17
|
+
@options = options
|
18
|
+
end
|
19
|
+
|
20
|
+
# @return [H2::Connection]
|
21
|
+
attr_reader :connection
|
22
|
+
|
23
|
+
# @return [Array<Symbol>] Returns a list of valid async request
|
24
|
+
# operation names.
|
25
|
+
def operation_names
|
26
|
+
self.class.api.async_operation_names
|
27
|
+
end
|
28
|
+
|
29
|
+
# Closes the underlying HTTP2 Connection for the client
|
30
|
+
# @return [Symbol] Returns the status of the connection (:closed)
|
31
|
+
def close_connection
|
32
|
+
@connection.close!
|
33
|
+
end
|
34
|
+
|
35
|
+
# Creates a new HTTP2 Connection for the client
|
36
|
+
# @return [Seahorse::Client::H2::Connection]
|
37
|
+
def new_connection
|
38
|
+
if @connection.closed?
|
39
|
+
@connection = H2::Connection.new(@options)
|
40
|
+
else
|
41
|
+
@connection
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def connection_errors
|
46
|
+
@connection.errors
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Seahorse
|
4
|
+
module Client
|
5
|
+
class AsyncResponse
|
6
|
+
|
7
|
+
def initialize(options = {})
|
8
|
+
@response = Response.new(context: options[:context])
|
9
|
+
@stream = options[:stream]
|
10
|
+
@stream_mutex = options[:stream_mutex]
|
11
|
+
@close_condition = options[:close_condition]
|
12
|
+
@sync_queue = options[:sync_queue]
|
13
|
+
end
|
14
|
+
|
15
|
+
def context
|
16
|
+
@response.context
|
17
|
+
end
|
18
|
+
|
19
|
+
def error
|
20
|
+
@response.error
|
21
|
+
end
|
22
|
+
|
23
|
+
def on(range, &block)
|
24
|
+
@response.on(range, &block)
|
25
|
+
self
|
26
|
+
end
|
27
|
+
|
28
|
+
def on_complete(&block)
|
29
|
+
@response.on_complete(&block)
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
def wait
|
34
|
+
if error && context.config.raise_response_errors
|
35
|
+
raise error
|
36
|
+
elsif @stream
|
37
|
+
# have a sync signal that #signal can be blocked on
|
38
|
+
# else, if #signal is called before #wait
|
39
|
+
# will be waiting for a signal never arrives
|
40
|
+
@sync_queue << "sync_signal"
|
41
|
+
# now #signal is unlocked for
|
42
|
+
# signaling close condition when ready
|
43
|
+
@stream_mutex.synchronize {
|
44
|
+
@close_condition.wait(@stream_mutex)
|
45
|
+
}
|
46
|
+
@response
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def join!
|
51
|
+
if error && context.config.raise_response_errors
|
52
|
+
raise error
|
53
|
+
elsif @stream
|
54
|
+
# close callback is waiting
|
55
|
+
# for the "sync_signal"
|
56
|
+
@sync_queue << "sync_signal"
|
57
|
+
@stream.close
|
58
|
+
@response
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/lib/seahorse/client/base.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'thread'
|
2
4
|
|
3
5
|
module Seahorse
|
@@ -12,6 +14,7 @@ module Seahorse
|
|
12
14
|
Plugins::NetHttp,
|
13
15
|
Plugins::RaiseResponseErrors,
|
14
16
|
Plugins::ResponseTarget,
|
17
|
+
Plugins::RequestCallback
|
15
18
|
])
|
16
19
|
|
17
20
|
# @api private
|
@@ -46,7 +49,7 @@ module Seahorse
|
|
46
49
|
# names. These are valid arguments to {#build_request} and are also
|
47
50
|
# valid methods.
|
48
51
|
def operation_names
|
49
|
-
self.class.api.operation_names
|
52
|
+
self.class.api.operation_names - self.class.api.async_operation_names
|
50
53
|
end
|
51
54
|
|
52
55
|
private
|
@@ -194,13 +197,15 @@ module Seahorse
|
|
194
197
|
private
|
195
198
|
|
196
199
|
def define_operation_methods
|
200
|
+
operations_module = Module.new
|
197
201
|
@api.operation_names.each do |method_name|
|
198
|
-
define_method
|
202
|
+
operations_module.send(:define_method, method_name) do |*args, &block|
|
199
203
|
params = args[0] || {}
|
200
204
|
options = args[1] || {}
|
201
205
|
build_request(method_name, params).send_request(options, &block)
|
202
206
|
end
|
203
207
|
end
|
208
|
+
include(operations_module)
|
204
209
|
end
|
205
210
|
|
206
211
|
def build_plugins
|
@@ -1,8 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Seahorse
|
2
4
|
module Client
|
3
5
|
class BlockIO
|
4
6
|
|
5
|
-
def initialize(&block)
|
7
|
+
def initialize(headers = nil, &block)
|
8
|
+
@headers = headers
|
6
9
|
@block = block
|
7
10
|
@size = 0
|
8
11
|
end
|
@@ -10,7 +13,8 @@ module Seahorse
|
|
10
13
|
# @param [String] chunk
|
11
14
|
# @return [Integer]
|
12
15
|
def write(chunk)
|
13
|
-
@block.call(chunk)
|
16
|
+
@block.call(chunk, @headers)
|
17
|
+
ensure
|
14
18
|
chunk.bytesize.tap { |chunk_size| @size += chunk_size }
|
15
19
|
end
|
16
20
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'set'
|
2
4
|
|
3
5
|
module Seahorse
|
@@ -104,7 +106,7 @@ module Seahorse
|
|
104
106
|
#
|
105
107
|
# @return [self]
|
106
108
|
def add_option(name, default = nil, &block)
|
107
|
-
default = DynamicDefault.new(
|
109
|
+
default = DynamicDefault.new(block) if block_given?
|
108
110
|
@defaults[name.to_sym] << default
|
109
111
|
self
|
110
112
|
end
|
@@ -193,11 +195,23 @@ module Seahorse
|
|
193
195
|
@members.include?(method_name) or super
|
194
196
|
end
|
195
197
|
|
198
|
+
def override_config(k, v)
|
199
|
+
@struct[k] = v
|
200
|
+
end
|
201
|
+
|
196
202
|
private
|
197
203
|
|
198
204
|
def value_at(opt_name)
|
199
205
|
value = @struct[opt_name]
|
200
|
-
value.is_a?(Defaults)
|
206
|
+
if value.is_a?(Defaults)
|
207
|
+
# this config value is used by endpoint discovery
|
208
|
+
if opt_name == :endpoint && @struct.members.include?(:regional_endpoint)
|
209
|
+
@struct[:regional_endpoint] = true
|
210
|
+
end
|
211
|
+
resolve_defaults(opt_name, value)
|
212
|
+
else
|
213
|
+
value
|
214
|
+
end
|
201
215
|
end
|
202
216
|
|
203
217
|
def resolve_defaults(opt_name, defaults)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Seahorse
|
2
4
|
module Client
|
3
5
|
module EventEmitter
|
@@ -9,7 +11,7 @@ module Seahorse
|
|
9
11
|
|
10
12
|
def emit(event_name, *args, &block)
|
11
13
|
@listeners[event_name] ||= []
|
12
|
-
@listeners[event_name] <<
|
14
|
+
@listeners[event_name] << block if block_given?
|
13
15
|
end
|
14
16
|
|
15
17
|
def signal(event, *args)
|
@@ -0,0 +1,250 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'http/2'
|
5
|
+
rescue LoadError; end
|
6
|
+
require 'openssl'
|
7
|
+
require 'socket'
|
8
|
+
|
9
|
+
module Seahorse
|
10
|
+
module Client
|
11
|
+
# @api private
|
12
|
+
module H2
|
13
|
+
|
14
|
+
# H2 Connection build on top of `http/2` gem
|
15
|
+
# (requires Ruby >= 2.1)
|
16
|
+
# with TLS layer plus ALPN, requires:
|
17
|
+
# Ruby >= 2.3 and OpenSSL >= 1.0.2
|
18
|
+
class Connection
|
19
|
+
|
20
|
+
OPTIONS = {
|
21
|
+
max_concurrent_streams: 100,
|
22
|
+
connection_timeout: 60,
|
23
|
+
connection_read_timeout: 60,
|
24
|
+
http_wire_trace: false,
|
25
|
+
logger: nil,
|
26
|
+
ssl_verify_peer: true,
|
27
|
+
ssl_ca_bundle: nil,
|
28
|
+
ssl_ca_directory: nil,
|
29
|
+
ssl_ca_store: nil,
|
30
|
+
enable_alpn: false
|
31
|
+
}
|
32
|
+
|
33
|
+
# chunk read size at socket
|
34
|
+
CHUNKSIZE = 1024
|
35
|
+
|
36
|
+
SOCKET_FAMILY = ::Socket::AF_INET
|
37
|
+
|
38
|
+
def initialize(options = {})
|
39
|
+
OPTIONS.each_pair do |opt_name, default_value|
|
40
|
+
value = options[opt_name].nil? ? default_value : options[opt_name]
|
41
|
+
instance_variable_set("@#{opt_name}", value)
|
42
|
+
end
|
43
|
+
@h2_client = HTTP2::Client.new(
|
44
|
+
settings_max_concurrent_streams: max_concurrent_streams
|
45
|
+
)
|
46
|
+
@logger = options[:logger] || Logger.new($stdout) if @http_wire_trace
|
47
|
+
@chunk_size = options[:read_chunk_size] || CHUNKSIZE
|
48
|
+
@errors = []
|
49
|
+
@status = :ready
|
50
|
+
@mutex = Mutex.new # connection can be shared across requests
|
51
|
+
@socket = nil
|
52
|
+
@socket_thread = nil
|
53
|
+
end
|
54
|
+
|
55
|
+
OPTIONS.keys.each do |attr_name|
|
56
|
+
attr_reader(attr_name)
|
57
|
+
end
|
58
|
+
|
59
|
+
alias ssl_verify_peer? ssl_verify_peer
|
60
|
+
|
61
|
+
attr_reader :errors
|
62
|
+
|
63
|
+
attr_accessor :input_signal_thread
|
64
|
+
|
65
|
+
def new_stream
|
66
|
+
begin
|
67
|
+
@h2_client.new_stream
|
68
|
+
rescue => error
|
69
|
+
raise Http2StreamInitializeError.new(error)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def connect(endpoint)
|
74
|
+
@mutex.synchronize {
|
75
|
+
if @status == :ready
|
76
|
+
tcp, addr = _tcp_socket(endpoint)
|
77
|
+
debug_output("opening connection to #{endpoint.host}:#{endpoint.port} ...")
|
78
|
+
_nonblocking_connect(tcp, addr)
|
79
|
+
debug_output('opened')
|
80
|
+
|
81
|
+
if endpoint.scheme == 'https'
|
82
|
+
@socket = OpenSSL::SSL::SSLSocket.new(tcp, _tls_context)
|
83
|
+
@socket.sync_close = true
|
84
|
+
@socket.hostname = endpoint.host
|
85
|
+
|
86
|
+
debug_output("starting TLS for #{endpoint.host}:#{endpoint.port} ...")
|
87
|
+
@socket.connect
|
88
|
+
debug_output('TLS established')
|
89
|
+
else
|
90
|
+
@socket = tcp
|
91
|
+
end
|
92
|
+
|
93
|
+
_register_h2_callbacks
|
94
|
+
@status = :active
|
95
|
+
elsif @status == :closed
|
96
|
+
msg = 'Async Client HTTP2 Connection is closed, you may'\
|
97
|
+
' use #new_connection to create a new HTTP2 Connection for this client'
|
98
|
+
raise Http2ConnectionClosedError.new(msg)
|
99
|
+
end
|
100
|
+
}
|
101
|
+
end
|
102
|
+
|
103
|
+
def start(stream)
|
104
|
+
@mutex.synchronize {
|
105
|
+
return if @socket_thread
|
106
|
+
@socket_thread = Thread.new do
|
107
|
+
while !@socket.closed?
|
108
|
+
begin
|
109
|
+
data = @socket.read_nonblock(@chunk_size)
|
110
|
+
@h2_client << data
|
111
|
+
rescue IO::WaitReadable
|
112
|
+
begin
|
113
|
+
unless IO.select([@socket], nil, nil, connection_read_timeout)
|
114
|
+
self.debug_output('socket connection read time out')
|
115
|
+
self.close!
|
116
|
+
else
|
117
|
+
# available, retry to start reading
|
118
|
+
retry
|
119
|
+
end
|
120
|
+
rescue
|
121
|
+
# error can happen when closing the socket
|
122
|
+
# while it's waiting for read
|
123
|
+
self.close!
|
124
|
+
end
|
125
|
+
rescue EOFError
|
126
|
+
self.close!
|
127
|
+
rescue => error
|
128
|
+
self.debug_output(error.inspect)
|
129
|
+
@errors << error
|
130
|
+
self.close!
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
@socket_thread.abort_on_exception = true
|
135
|
+
}
|
136
|
+
end
|
137
|
+
|
138
|
+
def close!
|
139
|
+
@mutex.synchronize {
|
140
|
+
self.debug_output('closing connection ...')
|
141
|
+
if @socket
|
142
|
+
@socket.close
|
143
|
+
@socket = nil
|
144
|
+
end
|
145
|
+
if @socket_thread
|
146
|
+
Thread.kill(@socket_thread)
|
147
|
+
@socket_thread = nil
|
148
|
+
end
|
149
|
+
@status = :closed
|
150
|
+
}
|
151
|
+
end
|
152
|
+
|
153
|
+
def closed?
|
154
|
+
@status == :closed
|
155
|
+
end
|
156
|
+
|
157
|
+
def debug_output(msg, type = nil)
|
158
|
+
prefix = case type
|
159
|
+
when :send then '-> '
|
160
|
+
when :receive then '<- '
|
161
|
+
else
|
162
|
+
''
|
163
|
+
end
|
164
|
+
return unless @logger
|
165
|
+
_debug_entry(prefix + msg)
|
166
|
+
end
|
167
|
+
|
168
|
+
private
|
169
|
+
|
170
|
+
def _debug_entry(str)
|
171
|
+
@logger << str
|
172
|
+
@logger << "\n"
|
173
|
+
end
|
174
|
+
|
175
|
+
def _register_h2_callbacks
|
176
|
+
@h2_client.on(:frame) do |bytes|
|
177
|
+
if @socket.nil?
|
178
|
+
msg = 'Connection is closed due to errors, '\
|
179
|
+
'you can find errors at async_client.connection.errors'
|
180
|
+
raise Http2ConnectionClosedError.new(msg)
|
181
|
+
else
|
182
|
+
@socket.print(bytes)
|
183
|
+
@socket.flush
|
184
|
+
end
|
185
|
+
end
|
186
|
+
@h2_client.on(:frame_sent) do |frame|
|
187
|
+
debug_output("frame: #{frame.inspect}", :send)
|
188
|
+
end
|
189
|
+
@h2_client.on(:frame_received) do |frame|
|
190
|
+
debug_output("frame: #{frame.inspect}", :receive)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def _tcp_socket(endpoint)
|
195
|
+
tcp = ::Socket.new(SOCKET_FAMILY, ::Socket::SOCK_STREAM, 0)
|
196
|
+
tcp.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, 1)
|
197
|
+
|
198
|
+
address = ::Socket.getaddrinfo(endpoint.host, nil, SOCKET_FAMILY).first[3]
|
199
|
+
sockaddr = ::Socket.sockaddr_in(endpoint.port, address)
|
200
|
+
|
201
|
+
[tcp, sockaddr]
|
202
|
+
end
|
203
|
+
|
204
|
+
def _nonblocking_connect(tcp, addr)
|
205
|
+
begin
|
206
|
+
tcp.connect_nonblock(addr)
|
207
|
+
rescue IO::WaitWritable
|
208
|
+
unless IO.select(nil, [tcp], nil, connection_timeout)
|
209
|
+
tcp.close
|
210
|
+
raise
|
211
|
+
end
|
212
|
+
begin
|
213
|
+
tcp.connect_nonblock(addr)
|
214
|
+
rescue Errno::EISCONN
|
215
|
+
# tcp socket connected, continue
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
def _tls_context
|
221
|
+
ssl_ctx = OpenSSL::SSL::SSLContext.new(:TLSv1_2)
|
222
|
+
if ssl_verify_peer?
|
223
|
+
ssl_ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
224
|
+
ssl_ctx.ca_file = ssl_ca_bundle ? ssl_ca_bundle : _default_ca_bundle
|
225
|
+
ssl_ctx.ca_path = ssl_ca_directory ? ssl_ca_directory : _default_ca_directory
|
226
|
+
ssl_ctx.cert_store = ssl_ca_store if ssl_ca_store
|
227
|
+
else
|
228
|
+
ssl_ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
229
|
+
end
|
230
|
+
if enable_alpn
|
231
|
+
debug_output('enabling ALPN for TLS ...')
|
232
|
+
ssl_ctx.alpn_protocols = ['h2']
|
233
|
+
end
|
234
|
+
ssl_ctx
|
235
|
+
end
|
236
|
+
|
237
|
+
def _default_ca_bundle
|
238
|
+
File.exist?(OpenSSL::X509::DEFAULT_CERT_FILE) ?
|
239
|
+
OpenSSL::X509::DEFAULT_CERT_FILE : nil
|
240
|
+
end
|
241
|
+
|
242
|
+
def _default_ca_directory
|
243
|
+
Dir.exist?(OpenSSL::X509::DEFAULT_CERT_DIR) ?
|
244
|
+
OpenSSL::X509::DEFAULT_CERT_DIR : nil
|
245
|
+
end
|
246
|
+
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'http/2'
|
5
|
+
rescue LoadError; end
|
6
|
+
|
7
|
+
require 'securerandom'
|
8
|
+
|
9
|
+
module Seahorse
|
10
|
+
module Client
|
11
|
+
# @api private
|
12
|
+
module H2
|
13
|
+
|
14
|
+
NETWORK_ERRORS = [
|
15
|
+
SocketError, EOFError, IOError, Timeout::Error,
|
16
|
+
Errno::ECONNABORTED, Errno::ECONNRESET, Errno::EPIPE,
|
17
|
+
Errno::EINVAL, Errno::ETIMEDOUT, OpenSSL::SSL::SSLError,
|
18
|
+
Errno::EHOSTUNREACH, Errno::ECONNREFUSED,# OpenSSL::SSL::SSLErrorWaitReadable
|
19
|
+
]
|
20
|
+
|
21
|
+
# @api private
|
22
|
+
DNS_ERROR_MESSAGES = [
|
23
|
+
'getaddrinfo: nodename nor servname provided, or not known', # MacOS
|
24
|
+
'getaddrinfo: Name or service not known' # GNU
|
25
|
+
]
|
26
|
+
|
27
|
+
class Handler < Client::Handler
|
28
|
+
|
29
|
+
def call(context)
|
30
|
+
stream = nil
|
31
|
+
begin
|
32
|
+
conn = context.client.connection
|
33
|
+
stream = conn.new_stream
|
34
|
+
|
35
|
+
stream_mutex = Mutex.new
|
36
|
+
close_condition = ConditionVariable.new
|
37
|
+
sync_queue = Queue.new
|
38
|
+
|
39
|
+
conn.connect(context.http_request.endpoint)
|
40
|
+
_register_callbacks(
|
41
|
+
context.http_response,
|
42
|
+
stream,
|
43
|
+
stream_mutex,
|
44
|
+
close_condition,
|
45
|
+
sync_queue
|
46
|
+
)
|
47
|
+
|
48
|
+
conn.debug_output("sending initial request ...")
|
49
|
+
if input_emitter = context[:input_event_emitter]
|
50
|
+
_send_initial_headers(context.http_request, stream)
|
51
|
+
|
52
|
+
# prepare for sending events later
|
53
|
+
input_emitter.stream = stream
|
54
|
+
# request sigv4 serves as the initial #prior_signature
|
55
|
+
input_emitter.encoder.prior_signature =
|
56
|
+
context.http_request.headers['authorization'].split('Signature=').last
|
57
|
+
input_emitter.validate_event = context.config.validate_params
|
58
|
+
else
|
59
|
+
_send_initial_headers(context.http_request, stream)
|
60
|
+
_send_initial_data(context.http_request, stream)
|
61
|
+
end
|
62
|
+
|
63
|
+
conn.start(stream)
|
64
|
+
rescue *NETWORK_ERRORS => error
|
65
|
+
error = NetworkingError.new(
|
66
|
+
error, error_message(context.http_request, error))
|
67
|
+
context.http_response.signal_error(error)
|
68
|
+
rescue => error
|
69
|
+
conn.debug_output(error.inspect)
|
70
|
+
# not retryable
|
71
|
+
context.http_response.signal_error(error)
|
72
|
+
end
|
73
|
+
|
74
|
+
AsyncResponse.new(
|
75
|
+
context: context,
|
76
|
+
stream: stream,
|
77
|
+
stream_mutex: stream_mutex,
|
78
|
+
close_condition: close_condition,
|
79
|
+
sync_queue: sync_queue
|
80
|
+
)
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def _register_callbacks(resp, stream, stream_mutex, close_condition, sync_queue)
|
86
|
+
stream.on(:headers) do |headers|
|
87
|
+
resp.signal_headers(headers)
|
88
|
+
end
|
89
|
+
|
90
|
+
stream.on(:data) do |data|
|
91
|
+
resp.signal_data(data)
|
92
|
+
end
|
93
|
+
|
94
|
+
stream.on(:close) do
|
95
|
+
resp.signal_done
|
96
|
+
# block until #wait is ready for signal
|
97
|
+
# else deadlock may happen because #signal happened
|
98
|
+
# eariler than #wait (see AsyncResponse#wait)
|
99
|
+
sync_queue.pop
|
100
|
+
stream_mutex.synchronize {
|
101
|
+
close_condition.signal
|
102
|
+
}
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def _send_initial_headers(req, stream)
|
107
|
+
begin
|
108
|
+
headers = _h2_headers(req)
|
109
|
+
stream.headers(headers, end_stream: false)
|
110
|
+
rescue => e
|
111
|
+
raise Http2InitialRequestError.new(e)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def _send_initial_data(req, stream)
|
116
|
+
begin
|
117
|
+
data = req.body.read
|
118
|
+
stream.data(data, end_stream: true)
|
119
|
+
rescue => e
|
120
|
+
raise Http2InitialRequestError.new(e)
|
121
|
+
end
|
122
|
+
data
|
123
|
+
end
|
124
|
+
|
125
|
+
# H2 pseudo headers
|
126
|
+
# https://http2.github.io/http2-spec/#rfc.section.8.1.2.3
|
127
|
+
def _h2_headers(req)
|
128
|
+
headers = {}
|
129
|
+
headers[':method'] = req.http_method.upcase
|
130
|
+
headers[':scheme'] = req.endpoint.scheme
|
131
|
+
headers[':path'] = req.endpoint.path.empty? ? '/' : req.endpoint.path
|
132
|
+
if req.endpoint.query && !req.endpoint.query.empty?
|
133
|
+
headers[':path'] += "?#{req.endpoint.query}"
|
134
|
+
end
|
135
|
+
req.headers.each {|k, v| headers[k.downcase] = v }
|
136
|
+
headers
|
137
|
+
end
|
138
|
+
|
139
|
+
def error_message(req, error)
|
140
|
+
if error.is_a?(SocketError) && DNS_ERROR_MESSAGES.include?(error.message)
|
141
|
+
host = req.endpoint.host
|
142
|
+
"unable to connect to `#{host}`; SocketError: #{error.message}"
|
143
|
+
else
|
144
|
+
error.message
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|