smithy-client 1.0.0.pre0 → 1.0.0.pre1
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 +2 -0
- data/VERSION +1 -1
- data/lib/smithy-client/anonymous_provider.rb +12 -0
- data/lib/smithy-client/auth_option.rb +23 -0
- data/lib/smithy-client/auth_scheme.rb +25 -0
- data/lib/smithy-client/auth_schemes/anonymous.rb +18 -0
- data/lib/smithy-client/auth_schemes/http_api_key.rb +18 -0
- data/lib/smithy-client/auth_schemes/http_basic.rb +18 -0
- data/lib/smithy-client/auth_schemes/http_bearer.rb +18 -0
- data/lib/smithy-client/auth_schemes/http_digest.rb +18 -0
- data/lib/smithy-client/base.rb +200 -0
- data/lib/smithy-client/block_io.rb +36 -0
- data/lib/smithy-client/configuration.rb +222 -0
- data/lib/smithy-client/default_params.rb +91 -0
- data/lib/smithy-client/dynamic_errors.rb +82 -0
- data/lib/smithy-client/endpoint_rules.rb +186 -0
- data/lib/smithy-client/handler.rb +29 -0
- data/lib/smithy-client/handler_builder.rb +33 -0
- data/lib/smithy-client/handler_context.rb +67 -0
- data/lib/smithy-client/handler_list.rb +197 -0
- data/lib/smithy-client/handler_list_entry.rb +102 -0
- data/lib/smithy-client/http/error_inspector.rb +87 -0
- data/lib/smithy-client/http/headers.rb +122 -0
- data/lib/smithy-client/http/request.rb +57 -0
- data/lib/smithy-client/http/response.rb +178 -0
- data/lib/smithy-client/http_api_key_provider.rb +18 -0
- data/lib/smithy-client/http_bearer_provider.rb +18 -0
- data/lib/smithy-client/http_login_provider.rb +19 -0
- data/lib/smithy-client/identities/anonymous.rb +10 -0
- data/lib/smithy-client/identities/http_api_key.rb +18 -0
- data/lib/smithy-client/identities/http_bearer.rb +18 -0
- data/lib/smithy-client/identities/http_login.rb +22 -0
- data/lib/smithy-client/identity.rb +15 -0
- data/lib/smithy-client/log_formatter.rb +215 -0
- data/lib/smithy-client/log_param_filter.rb +88 -0
- data/lib/smithy-client/log_param_formatter.rb +65 -0
- data/lib/smithy-client/managed_file.rb +14 -0
- data/lib/smithy-client/net_http/connection_pool.rb +297 -0
- data/lib/smithy-client/net_http/handler.rb +160 -0
- data/lib/smithy-client/net_http/patches.rb +28 -0
- data/lib/smithy-client/networking_error.rb +16 -0
- data/lib/smithy-client/pageable_response.rb +138 -0
- data/lib/smithy-client/param_converter.rb +243 -0
- data/lib/smithy-client/param_validator.rb +213 -0
- data/lib/smithy-client/plugin.rb +144 -0
- data/lib/smithy-client/plugin_list.rb +141 -0
- data/lib/smithy-client/plugins/anonymous_auth.rb +23 -0
- data/lib/smithy-client/plugins/checksum_required.rb +51 -0
- data/lib/smithy-client/plugins/content_length.rb +26 -0
- data/lib/smithy-client/plugins/default_params.rb +22 -0
- data/lib/smithy-client/plugins/host_prefix.rb +69 -0
- data/lib/smithy-client/plugins/http_api_key_auth.rb +37 -0
- data/lib/smithy-client/plugins/http_basic_auth.rb +47 -0
- data/lib/smithy-client/plugins/http_bearer_auth.rb +37 -0
- data/lib/smithy-client/plugins/http_digest_auth.rb +60 -0
- data/lib/smithy-client/plugins/idempotency_token.rb +34 -0
- data/lib/smithy-client/plugins/logging.rb +56 -0
- data/lib/smithy-client/plugins/net_http.rb +163 -0
- data/lib/smithy-client/plugins/pageable_response.rb +37 -0
- data/lib/smithy-client/plugins/param_converter.rb +32 -0
- data/lib/smithy-client/plugins/param_validator.rb +30 -0
- data/lib/smithy-client/plugins/protocol.rb +66 -0
- data/lib/smithy-client/plugins/raise_response_errors.rb +33 -0
- data/lib/smithy-client/plugins/request_compression.rb +200 -0
- data/lib/smithy-client/plugins/response_target.rb +71 -0
- data/lib/smithy-client/plugins/retry_errors.rb +125 -0
- data/lib/smithy-client/plugins/sign_requests.rb +24 -0
- data/lib/smithy-client/plugins/stub_responses.rb +102 -0
- data/lib/smithy-client/protocol_spec_matcher.rb +60 -0
- data/lib/smithy-client/refreshing_identity_provider.rb +65 -0
- data/lib/smithy-client/request.rb +76 -0
- data/lib/smithy-client/response.rb +48 -0
- data/lib/smithy-client/retry/adaptive.rb +66 -0
- data/lib/smithy-client/retry/client_rate_limiter.rb +142 -0
- data/lib/smithy-client/retry/quota.rb +58 -0
- data/lib/smithy-client/retry/standard.rb +52 -0
- data/lib/smithy-client/retry.rb +36 -0
- data/lib/smithy-client/rpc_v2_cbor/protocol.rb +38 -0
- data/lib/smithy-client/rpc_v2_cbor/request_builder.rb +76 -0
- data/lib/smithy-client/rpc_v2_cbor/response_parser.rb +86 -0
- data/lib/smithy-client/rpc_v2_cbor/response_stubber.rb +34 -0
- data/lib/smithy-client/service_error.rb +57 -0
- data/lib/smithy-client/signer.rb +16 -0
- data/lib/smithy-client/signers/anonymous.rb +13 -0
- data/lib/smithy-client/signers/http_api_key.rb +52 -0
- data/lib/smithy-client/signers/http_basic.rb +23 -0
- data/lib/smithy-client/signers/http_bearer.rb +19 -0
- data/lib/smithy-client/signers/http_digest.rb +21 -0
- data/lib/smithy-client/stubbing/data_applicator.rb +61 -0
- data/lib/smithy-client/stubbing/empty_stub.rb +69 -0
- data/lib/smithy-client/stubbing/endpoint_provider.rb +22 -0
- data/lib/smithy-client/stubbing/protocol.rb +29 -0
- data/lib/smithy-client/stubbing/stub_data.rb +25 -0
- data/lib/smithy-client/stubbing.rb +14 -0
- data/lib/smithy-client/stubs.rb +212 -0
- data/lib/smithy-client/util.rb +15 -0
- data/lib/smithy-client/waiters/poller.rb +93 -0
- data/lib/smithy-client/waiters/waiter.rb +113 -0
- data/lib/smithy-client.rb +66 -1
- metadata +163 -9
@@ -0,0 +1,102 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Smithy
|
4
|
+
module Client
|
5
|
+
# A container for an un-constructed handler. A handler entry has the
|
6
|
+
# handler class, and information about handler priority/order.
|
7
|
+
#
|
8
|
+
# This class is an implementation detail of the {HandlerList} class.
|
9
|
+
# Do not rely on public interfaces of this class.
|
10
|
+
class HandlerListEntry
|
11
|
+
# @api private
|
12
|
+
STEPS = {
|
13
|
+
initialize: 600,
|
14
|
+
validate: 500,
|
15
|
+
build: 400,
|
16
|
+
retry: 300,
|
17
|
+
parse: 200,
|
18
|
+
sign: 100,
|
19
|
+
send: 0
|
20
|
+
}.freeze
|
21
|
+
|
22
|
+
# @option options [Handler, Class<Handler>] :handler_class
|
23
|
+
# @option options [Integer] :inserted The insertion
|
24
|
+
# order/position. This is used to determine sort order when two
|
25
|
+
# entries have the same priority.
|
26
|
+
# @option options [Symbol] :step (:build)
|
27
|
+
# @option options [Integer] :priority (50)
|
28
|
+
# @option options [Set<String>, nil] :operations (nil)
|
29
|
+
def initialize(options)
|
30
|
+
@options = options
|
31
|
+
@handler_class = options[:handler_class]
|
32
|
+
@inserted = options[:inserted]
|
33
|
+
@operations = Set.new(options[:operations]) if options[:operations]
|
34
|
+
self.step = options[:step] || :build
|
35
|
+
self.priority = options[:priority] || 50
|
36
|
+
compute_weight
|
37
|
+
end
|
38
|
+
|
39
|
+
# @return [Handler, Class<Handler>] Returns the handler. This may
|
40
|
+
# be a constructed handler object or a handler class.
|
41
|
+
attr_reader :handler_class
|
42
|
+
|
43
|
+
# @return [Integer] The insertion order/position. This is used to
|
44
|
+
# determine sort order when two entries have the same priority.
|
45
|
+
# Entries inserted later (with a higher inserted value) have a
|
46
|
+
# lower priority.
|
47
|
+
attr_reader :inserted
|
48
|
+
|
49
|
+
# @return [Symbol]
|
50
|
+
attr_reader :step
|
51
|
+
|
52
|
+
# @return [Integer]
|
53
|
+
attr_reader :priority
|
54
|
+
|
55
|
+
# @return [Set<String>, nil]
|
56
|
+
attr_reader :operations
|
57
|
+
|
58
|
+
# @return [Integer]
|
59
|
+
attr_reader :weight
|
60
|
+
|
61
|
+
# @return [Integer]
|
62
|
+
def <=>(other)
|
63
|
+
if weight == other.weight
|
64
|
+
other.inserted <=> inserted
|
65
|
+
else
|
66
|
+
weight <=> other.weight
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# @option options (see #initialize)
|
71
|
+
# @return [HandlerListEntry]
|
72
|
+
def copy(options = {})
|
73
|
+
HandlerListEntry.new(@options.merge(options))
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def step=(step)
|
79
|
+
if STEPS.key?(step)
|
80
|
+
@step = step
|
81
|
+
else
|
82
|
+
msg = "invalid :step `%s', must be one of :initialize, :validate, " \
|
83
|
+
':build, :retry, :parse, :sign or :send'
|
84
|
+
raise ArgumentError, msg % step.inspect
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def priority=(priority)
|
89
|
+
if (0..99).include?(priority)
|
90
|
+
@priority = priority
|
91
|
+
else
|
92
|
+
msg = "invalid :priority `%s', must be between 0 and 99"
|
93
|
+
raise ArgumentError, msg % priority.inspect
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def compute_weight
|
98
|
+
@weight = STEPS[@step] + @priority
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'time'
|
4
|
+
|
5
|
+
module Smithy
|
6
|
+
module Client
|
7
|
+
module HTTP
|
8
|
+
# An HTTP error inspector, using hints from status code and headers.
|
9
|
+
class ErrorInspector
|
10
|
+
def initialize(error, http_response)
|
11
|
+
@error = error
|
12
|
+
@http_response = http_response
|
13
|
+
end
|
14
|
+
|
15
|
+
def retryable?
|
16
|
+
(modeled_retryable? ||
|
17
|
+
throttling? ||
|
18
|
+
transient? ||
|
19
|
+
server?) &&
|
20
|
+
# IO does not respond to #truncate and is not rewindable
|
21
|
+
@http_response.body.respond_to?(:truncate)
|
22
|
+
end
|
23
|
+
|
24
|
+
def error_type
|
25
|
+
if transient?
|
26
|
+
'Transient'
|
27
|
+
elsif throttling?
|
28
|
+
'Throttling'
|
29
|
+
elsif server?
|
30
|
+
'ServerError'
|
31
|
+
elsif client?
|
32
|
+
'ClientError'
|
33
|
+
else
|
34
|
+
'Unknown'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def hints
|
39
|
+
hints = {}
|
40
|
+
if (retry_after = retry_after_hint)
|
41
|
+
hints[:retry_after] = retry_after
|
42
|
+
end
|
43
|
+
hints
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def transient?
|
49
|
+
@error.is_a?(NetworkingError)
|
50
|
+
end
|
51
|
+
|
52
|
+
def throttling?
|
53
|
+
@http_response.status_code == 429 || modeled_throttling?
|
54
|
+
end
|
55
|
+
|
56
|
+
def server?
|
57
|
+
(500..599).cover?(@http_response.status_code)
|
58
|
+
end
|
59
|
+
|
60
|
+
def client?
|
61
|
+
(400..499).cover?(@http_response.status_code)
|
62
|
+
end
|
63
|
+
|
64
|
+
def modeled_retryable?
|
65
|
+
@error.is_a?(ServiceError) && @error.retryable?
|
66
|
+
end
|
67
|
+
|
68
|
+
def modeled_throttling?
|
69
|
+
modeled_retryable? && @error.throttling?
|
70
|
+
end
|
71
|
+
|
72
|
+
def retry_after_hint
|
73
|
+
retry_after = @http_response.headers['retry-after']
|
74
|
+
Integer(retry_after)
|
75
|
+
rescue ArgumentError # string is present, assume it is a date
|
76
|
+
begin
|
77
|
+
Time.parse(retry_after) - Time.now
|
78
|
+
rescue ArgumentError # empty string, somehow
|
79
|
+
nil
|
80
|
+
end
|
81
|
+
rescue TypeError # header is not present
|
82
|
+
nil
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Smithy
|
4
|
+
module Client
|
5
|
+
module HTTP
|
6
|
+
# Provides a Hash-like interface for HTTP headers. Header names
|
7
|
+
# are treated indifferently as lower-cased strings. Header values
|
8
|
+
# are cast to strings.
|
9
|
+
#
|
10
|
+
# headers = HTTP::Headers.new
|
11
|
+
# headers['Content-Length'] = 100
|
12
|
+
# headers[:Authorization] = 'Abc'
|
13
|
+
#
|
14
|
+
# headers.keys
|
15
|
+
# #=> ['content-length', 'authorization']
|
16
|
+
#
|
17
|
+
# headers.values
|
18
|
+
# #=> ['100', 'Abc']
|
19
|
+
#
|
20
|
+
# You can get the header values as a vanilla hash by calling {#to_h}:
|
21
|
+
#
|
22
|
+
# headers.to_h
|
23
|
+
# #=> { 'content-length' => '100', 'authorization' => 'Abc' }
|
24
|
+
#
|
25
|
+
class Headers
|
26
|
+
include Enumerable
|
27
|
+
|
28
|
+
# @api private
|
29
|
+
def initialize(headers = {})
|
30
|
+
@data = {}
|
31
|
+
headers.each_pair do |key, value|
|
32
|
+
self[key] = value
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# @yield [key, value]
|
37
|
+
# @yieldparam [String] key
|
38
|
+
# @yieldparam [String] value
|
39
|
+
# @return [nil]
|
40
|
+
def each(&)
|
41
|
+
if block_given?
|
42
|
+
@data.each_pair(&)
|
43
|
+
nil
|
44
|
+
else
|
45
|
+
@data.enum_for(:each)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
alias each_pair each
|
49
|
+
|
50
|
+
# @param [String] key
|
51
|
+
# @return [String]
|
52
|
+
def [](key)
|
53
|
+
@data[key.to_s.downcase]
|
54
|
+
end
|
55
|
+
|
56
|
+
# @param [String] key
|
57
|
+
# @param [String] value
|
58
|
+
def []=(key, value)
|
59
|
+
@data[key.to_s.downcase] = value.to_s
|
60
|
+
end
|
61
|
+
|
62
|
+
# @param [Hash] headers
|
63
|
+
# @return [Headers]
|
64
|
+
def update(headers)
|
65
|
+
headers.each_pair do |k, v|
|
66
|
+
self[k] = v
|
67
|
+
end
|
68
|
+
self
|
69
|
+
end
|
70
|
+
|
71
|
+
# @param [String] key
|
72
|
+
def delete(key)
|
73
|
+
@data.delete(key.to_s.downcase)
|
74
|
+
end
|
75
|
+
|
76
|
+
# @return [Headers]
|
77
|
+
def clear
|
78
|
+
@data = {}
|
79
|
+
self
|
80
|
+
end
|
81
|
+
|
82
|
+
# @return [Boolean]
|
83
|
+
def empty?
|
84
|
+
@data.empty?
|
85
|
+
end
|
86
|
+
|
87
|
+
# @return [Array<String>]
|
88
|
+
def keys
|
89
|
+
@data.keys
|
90
|
+
end
|
91
|
+
|
92
|
+
# @return [Array<String>]
|
93
|
+
def values
|
94
|
+
@data.values
|
95
|
+
end
|
96
|
+
|
97
|
+
# @return [Array<String>]
|
98
|
+
def values_at(*keys)
|
99
|
+
@data.values_at(*keys.map { |key| key.to_s.downcase })
|
100
|
+
end
|
101
|
+
|
102
|
+
# @return [Boolean] Returns `true` if the header is set.
|
103
|
+
def key?(key)
|
104
|
+
@data.key?(key.to_s.downcase)
|
105
|
+
end
|
106
|
+
alias has_key? key?
|
107
|
+
alias include? key?
|
108
|
+
|
109
|
+
# @return [Hash]
|
110
|
+
def to_hash
|
111
|
+
@data.dup
|
112
|
+
end
|
113
|
+
alias to_h to_hash
|
114
|
+
|
115
|
+
# @api private
|
116
|
+
def inspect
|
117
|
+
@data.inspect
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'stringio'
|
4
|
+
|
5
|
+
module Smithy
|
6
|
+
module Client
|
7
|
+
module HTTP
|
8
|
+
# Represents an HTTP request.
|
9
|
+
class Request
|
10
|
+
# @option options [String, URI::HTTP, URI::HTTPS, nil] :endpoint (nil)
|
11
|
+
# @option options [String] :http_method ('GET')
|
12
|
+
# @option options [Headers] :headers (Headers.new)
|
13
|
+
# @option options [IO, StringIO, #read, #size, #rewind] :body (StringIO.new)
|
14
|
+
def initialize(options = {})
|
15
|
+
self.endpoint = options[:endpoint]
|
16
|
+
@http_method = options[:http_method] || 'GET'
|
17
|
+
@headers = Headers.new(options[:headers] || {})
|
18
|
+
self.body = options[:body]
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [URI::HTTP, URI::HTTPS, nil]
|
22
|
+
attr_reader :endpoint
|
23
|
+
|
24
|
+
# @return [String]
|
25
|
+
attr_accessor :http_method
|
26
|
+
|
27
|
+
# @return [Headers]
|
28
|
+
attr_reader :headers
|
29
|
+
|
30
|
+
# @return [IO, StringIO]
|
31
|
+
attr_reader :body
|
32
|
+
|
33
|
+
# @param [String, URI::HTTP, URI::HTTPS, nil] endpoint
|
34
|
+
def endpoint=(endpoint)
|
35
|
+
endpoint = URI.parse(endpoint) if endpoint.is_a?(String)
|
36
|
+
unless endpoint.nil? || endpoint.is_a?(URI::HTTP) || endpoint.is_a?(URI::HTTPS)
|
37
|
+
msg = 'invalid endpoint, expected URI::HTTP, URI::HTTPS, or nil, ' \
|
38
|
+
"got #{endpoint.inspect}"
|
39
|
+
raise ArgumentError, msg
|
40
|
+
end
|
41
|
+
|
42
|
+
@endpoint = endpoint
|
43
|
+
end
|
44
|
+
|
45
|
+
# @param [#read, #size, #rewind] io
|
46
|
+
def body=(io)
|
47
|
+
@body =
|
48
|
+
case io
|
49
|
+
when nil then StringIO.new
|
50
|
+
when String then StringIO.new(io)
|
51
|
+
else io
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,178 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'stringio'
|
4
|
+
|
5
|
+
module Smithy
|
6
|
+
module Client
|
7
|
+
module HTTP
|
8
|
+
# Represents an HTTP Response.
|
9
|
+
class Response
|
10
|
+
# @option options [Integer] :status_code (0)
|
11
|
+
# @option options [Headers] :headers (Headers.new)
|
12
|
+
# @option options [IO] :body (StringIO.new)
|
13
|
+
def initialize(options = {})
|
14
|
+
@status_code = options[:status_code] || 0
|
15
|
+
@headers = Headers.new(options[:headers] || {})
|
16
|
+
self.body = options[:body]
|
17
|
+
|
18
|
+
@listeners = Hash.new { |h, k| h[k] = [] }
|
19
|
+
@done = nil
|
20
|
+
@error = nil
|
21
|
+
end
|
22
|
+
|
23
|
+
# @return [Integer]
|
24
|
+
attr_accessor :status_code
|
25
|
+
|
26
|
+
# @return [Headers]
|
27
|
+
attr_reader :headers
|
28
|
+
|
29
|
+
# @return [IO, StringIO]
|
30
|
+
attr_reader :body
|
31
|
+
|
32
|
+
# @return [StandardError, nil]
|
33
|
+
attr_reader :error
|
34
|
+
|
35
|
+
# @param [#read, #size, #rewind] io
|
36
|
+
def body=(io)
|
37
|
+
@body =
|
38
|
+
case io
|
39
|
+
when nil then StringIO.new
|
40
|
+
when String then StringIO.new(io)
|
41
|
+
else io
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# @param [Integer] status_code
|
46
|
+
# @param [Hash<String, String>] headers
|
47
|
+
def signal_headers(status_code, headers)
|
48
|
+
@status_code = status_code
|
49
|
+
@headers = Headers.new(headers)
|
50
|
+
emit(:headers, @status_code, @headers)
|
51
|
+
end
|
52
|
+
|
53
|
+
# @param [string] chunk
|
54
|
+
def signal_data(chunk)
|
55
|
+
return if chunk == ''
|
56
|
+
|
57
|
+
@body.write(chunk)
|
58
|
+
emit(:data, chunk)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Completes the http response.
|
62
|
+
#
|
63
|
+
# @example Completing the response in a single call
|
64
|
+
#
|
65
|
+
# http_response.signal_done(
|
66
|
+
# status_code: 200,
|
67
|
+
# headers: {},
|
68
|
+
# body: ''
|
69
|
+
# )
|
70
|
+
#
|
71
|
+
# @example Complete the response in parts
|
72
|
+
#
|
73
|
+
# # signal headers straight-way
|
74
|
+
# http_response.signal_headers(200, {})
|
75
|
+
#
|
76
|
+
# # signal data as it is received from the socket
|
77
|
+
# http_response.signal_data("...")
|
78
|
+
# http_response.signal_data("...")
|
79
|
+
# http_response.signal_data("...")
|
80
|
+
#
|
81
|
+
# # signal done once the body data is all written
|
82
|
+
# http_response.signal_done
|
83
|
+
#
|
84
|
+
# @overload signal_done()
|
85
|
+
#
|
86
|
+
# @overload signal_done(options = {})
|
87
|
+
# @option options [required, Integer] :status_code
|
88
|
+
# @option options [required, Hash] :headers
|
89
|
+
# @option options [required, String] :body
|
90
|
+
#
|
91
|
+
def signal_done(options = {})
|
92
|
+
if options.keys.sort == %i[body headers status_code]
|
93
|
+
signal_headers(options[:status_code], options[:headers])
|
94
|
+
signal_data(options[:body])
|
95
|
+
signal_done
|
96
|
+
elsif options.empty?
|
97
|
+
@body.rewind if @body.respond_to?(:rewind)
|
98
|
+
@done = true
|
99
|
+
emit(:done)
|
100
|
+
else
|
101
|
+
msg = 'options must be empty or must contain :status_code, :headers, ' \
|
102
|
+
'and :body'
|
103
|
+
raise ArgumentError, msg
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# @param [StandardError] error
|
108
|
+
def signal_error(error)
|
109
|
+
@error = error
|
110
|
+
signal_done
|
111
|
+
end
|
112
|
+
|
113
|
+
# @param [Integer, Range<Integer>] status_code_range
|
114
|
+
# @yield A block to be called when headers are received.
|
115
|
+
def on_headers(status_code_range = nil, &block)
|
116
|
+
@listeners[:headers] << listener(status_code_range, block)
|
117
|
+
end
|
118
|
+
|
119
|
+
# @yield A block to be called when data is received.
|
120
|
+
def on_data(&block)
|
121
|
+
@listeners[:data] << block
|
122
|
+
end
|
123
|
+
|
124
|
+
# @param [Integer, Range<Integer>] status_code_range
|
125
|
+
# @yield A block to be called when the response is complete.
|
126
|
+
def on_done(status_code_range = nil, &block)
|
127
|
+
listener = listener(status_code_range, block)
|
128
|
+
if @done
|
129
|
+
listener.call
|
130
|
+
else
|
131
|
+
@listeners[:done] << listener
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
# @param [Integer, Range<Integer>] status_code_range
|
136
|
+
# @yield A block to be called when the response is successful.
|
137
|
+
def on_success(status_code_range = 200..599)
|
138
|
+
on_done(status_code_range) do
|
139
|
+
yield unless @error
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
# @yieldparam [StandardError] error
|
144
|
+
# @yield A block to be called when an error occurs.
|
145
|
+
def on_error
|
146
|
+
on_done(0..599) do
|
147
|
+
yield(@error) if @error
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
# Resets the HTTP response.
|
152
|
+
def reset
|
153
|
+
@status_code = 0
|
154
|
+
@headers.clear
|
155
|
+
@body.truncate(0)
|
156
|
+
@error = nil
|
157
|
+
end
|
158
|
+
|
159
|
+
private
|
160
|
+
|
161
|
+
def listener(range, block)
|
162
|
+
range = range..range if range.is_a?(Integer)
|
163
|
+
if range
|
164
|
+
lambda do |*args|
|
165
|
+
block.call(*args) if range.include?(@status_code)
|
166
|
+
end
|
167
|
+
else
|
168
|
+
block
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def emit(event_name, *args)
|
173
|
+
@listeners[event_name].each { |listener| listener.call(*args) }
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Smithy
|
4
|
+
module Client
|
5
|
+
# Returns an HTTP API key identity
|
6
|
+
class HttpApiKeyProvider
|
7
|
+
# @param [String] key
|
8
|
+
def initialize(key)
|
9
|
+
@identity = Identities::HttpApiKey.new(key: key)
|
10
|
+
end
|
11
|
+
|
12
|
+
# @return [Identities::HttpApiKey]
|
13
|
+
def identity(_properties)
|
14
|
+
@identity
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Smithy
|
4
|
+
module Client
|
5
|
+
# Returns an HTTP Bearer identity
|
6
|
+
class HttpBearerProvider
|
7
|
+
# @param [String] token
|
8
|
+
def initialize(token)
|
9
|
+
@identity = Identities::HttpBearer.new(token: token)
|
10
|
+
end
|
11
|
+
|
12
|
+
# @return [Identities::HttpBearer]
|
13
|
+
def identity(_properties)
|
14
|
+
@identity
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Smithy
|
4
|
+
module Client
|
5
|
+
# Returns an HTTP login identity
|
6
|
+
class HttpLoginProvider
|
7
|
+
# @param [String] username
|
8
|
+
# @param [String] password
|
9
|
+
def initialize(username, password)
|
10
|
+
@identity = Identities::HttpLogin.new(username: username, password: password)
|
11
|
+
end
|
12
|
+
|
13
|
+
# @return [Identities::HttpLogin]
|
14
|
+
def identity(_properties)
|
15
|
+
@identity
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Smithy
|
4
|
+
module Client
|
5
|
+
module Identities
|
6
|
+
# Identity class for HTTP API Key authentication.
|
7
|
+
class HttpApiKey < Identity
|
8
|
+
def initialize(key:, **)
|
9
|
+
@key = key
|
10
|
+
super(**)
|
11
|
+
end
|
12
|
+
|
13
|
+
# @return [String, nil]
|
14
|
+
attr_reader :key
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Smithy
|
4
|
+
module Client
|
5
|
+
module Identities
|
6
|
+
# Identity class for HTTP Bearer token authentication.
|
7
|
+
class HttpBearer < Identity
|
8
|
+
def initialize(token:, **)
|
9
|
+
@token = token
|
10
|
+
super(**)
|
11
|
+
end
|
12
|
+
|
13
|
+
# @return [String, nil]
|
14
|
+
attr_reader :token
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Smithy
|
4
|
+
module Client
|
5
|
+
module Identities
|
6
|
+
# Identity class for HTTP login authentication.
|
7
|
+
class HttpLogin < Identity
|
8
|
+
def initialize(username:, password:, **)
|
9
|
+
@username = username
|
10
|
+
@password = password
|
11
|
+
super(**)
|
12
|
+
end
|
13
|
+
|
14
|
+
# @return [String]
|
15
|
+
attr_reader :username
|
16
|
+
|
17
|
+
# @return [String]
|
18
|
+
attr_reader :password
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Smithy
|
4
|
+
module Client
|
5
|
+
# Base class for all Identity classes.
|
6
|
+
class Identity
|
7
|
+
def initialize(expiration: nil)
|
8
|
+
@expiration = expiration
|
9
|
+
end
|
10
|
+
|
11
|
+
# @return [Time, nil]
|
12
|
+
attr_reader :expiration
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|