hearth 1.0.0.pre1 → 1.0.0.pre3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (176) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -4
  3. data/VERSION +1 -1
  4. data/lib/hearth/anonymous_auth_resolver.rb +11 -0
  5. data/lib/hearth/api_error.rb +15 -1
  6. data/lib/hearth/auth_option.rb +21 -0
  7. data/lib/hearth/auth_schemes/anonymous.rb +21 -0
  8. data/lib/hearth/auth_schemes/http_api_key.rb +16 -0
  9. data/lib/hearth/auth_schemes/http_basic.rb +16 -0
  10. data/lib/hearth/auth_schemes/http_bearer.rb +16 -0
  11. data/lib/hearth/auth_schemes/http_digest.rb +16 -0
  12. data/lib/hearth/auth_schemes.rb +32 -0
  13. data/lib/hearth/checksums.rb +31 -0
  14. data/lib/hearth/client.rb +66 -0
  15. data/lib/hearth/client_stubs.rb +128 -0
  16. data/lib/hearth/config/env_provider.rb +53 -0
  17. data/lib/hearth/config/resolver.rb +53 -0
  18. data/lib/hearth/configuration.rb +15 -0
  19. data/lib/hearth/connection_pool.rb +77 -0
  20. data/lib/hearth/context.rb +29 -4
  21. data/lib/hearth/dns/host_address.rb +27 -0
  22. data/lib/hearth/dns/host_resolver.rb +92 -0
  23. data/lib/hearth/dns.rb +48 -0
  24. data/lib/hearth/endpoint_rules.rb +154 -0
  25. data/lib/hearth/http/api_error.rb +4 -8
  26. data/lib/hearth/http/client.rb +206 -59
  27. data/lib/hearth/http/error_inspector.rb +85 -0
  28. data/lib/hearth/http/error_parser.rb +18 -20
  29. data/lib/hearth/http/field.rb +49 -0
  30. data/lib/hearth/http/fields.rb +117 -0
  31. data/lib/hearth/http/header_list_builder.rb +42 -0
  32. data/lib/hearth/http/header_list_parser.rb +92 -0
  33. data/lib/hearth/http/middleware/content_length.rb +7 -4
  34. data/lib/hearth/http/middleware/content_md5.rb +30 -0
  35. data/lib/hearth/http/middleware/request_compression.rb +154 -0
  36. data/lib/hearth/http/middleware.rb +12 -0
  37. data/lib/hearth/http/networking_error.rb +1 -14
  38. data/lib/hearth/http/request.rb +83 -56
  39. data/lib/hearth/http/response.rb +42 -13
  40. data/lib/hearth/http.rb +16 -5
  41. data/lib/hearth/identities/anonymous.rb +8 -0
  42. data/lib/hearth/identities/http_api_key.rb +16 -0
  43. data/lib/hearth/identities/http_bearer.rb +16 -0
  44. data/lib/hearth/identities/http_login.rb +20 -0
  45. data/lib/hearth/identities.rb +21 -0
  46. data/lib/hearth/identity_provider.rb +17 -0
  47. data/lib/hearth/interceptor.rb +506 -0
  48. data/lib/hearth/interceptor_context.rb +40 -0
  49. data/lib/hearth/interceptor_list.rb +48 -0
  50. data/lib/hearth/interceptors.rb +76 -0
  51. data/lib/hearth/json.rb +4 -4
  52. data/lib/hearth/middleware/auth.rb +103 -0
  53. data/lib/hearth/middleware/build.rb +32 -1
  54. data/lib/hearth/middleware/endpoint.rb +79 -0
  55. data/lib/hearth/middleware/host_prefix.rb +11 -8
  56. data/lib/hearth/middleware/initialize.rb +57 -0
  57. data/lib/hearth/middleware/parse.rb +45 -7
  58. data/lib/hearth/middleware/retry.rb +105 -24
  59. data/lib/hearth/middleware/send.rb +137 -26
  60. data/lib/hearth/middleware/sign.rb +65 -0
  61. data/lib/hearth/middleware/validate.rb +11 -1
  62. data/lib/hearth/middleware.rb +20 -8
  63. data/lib/hearth/middleware_stack.rb +2 -44
  64. data/lib/hearth/networking_error.rb +18 -0
  65. data/lib/hearth/number_helper.rb +3 -3
  66. data/lib/hearth/output.rb +8 -4
  67. data/lib/hearth/plugin_list.rb +53 -0
  68. data/lib/hearth/query/param.rb +56 -0
  69. data/lib/hearth/query/param_list.rb +54 -0
  70. data/lib/hearth/query/param_matcher.rb +31 -0
  71. data/lib/hearth/refreshing_identity_provider.rb +63 -0
  72. data/lib/hearth/request.rb +22 -0
  73. data/lib/hearth/response.rb +36 -0
  74. data/lib/hearth/retry/adaptive.rb +60 -0
  75. data/lib/hearth/retry/capacity_not_available_error.rb +9 -0
  76. data/lib/hearth/retry/client_rate_limiter.rb +145 -0
  77. data/lib/hearth/retry/exponential_backoff.rb +15 -0
  78. data/lib/hearth/retry/retry_quota.rb +56 -0
  79. data/lib/hearth/retry/standard.rb +46 -0
  80. data/lib/hearth/retry.rb +29 -0
  81. data/lib/hearth/signers/anonymous.rb +16 -0
  82. data/lib/hearth/signers/http_api_key.rb +29 -0
  83. data/lib/hearth/signers/http_basic.rb +23 -0
  84. data/lib/hearth/signers/http_bearer.rb +19 -0
  85. data/lib/hearth/signers/http_digest.rb +19 -0
  86. data/lib/hearth/signers.rb +23 -0
  87. data/lib/hearth/structure.rb +7 -3
  88. data/lib/hearth/stubs.rb +38 -0
  89. data/lib/hearth/time_helper.rb +6 -5
  90. data/lib/hearth/validator.rb +60 -5
  91. data/lib/hearth/waiters/poller.rb +10 -9
  92. data/lib/hearth/waiters/waiter.rb +23 -9
  93. data/lib/hearth/xml/formatter.rb +11 -2
  94. data/lib/hearth/xml/node.rb +2 -3
  95. data/lib/hearth/xml/node_matcher.rb +0 -1
  96. data/lib/hearth.rb +37 -6
  97. data/sig/lib/hearth/aliases.rbs +6 -0
  98. data/sig/lib/hearth/anonymous_auth_resolver.rbs +5 -0
  99. data/sig/lib/hearth/api_error.rbs +13 -0
  100. data/sig/lib/hearth/auth_option.rbs +11 -0
  101. data/sig/lib/hearth/auth_schemes/anonymous.rbs +7 -0
  102. data/sig/lib/hearth/auth_schemes/http_api_key.rbs +7 -0
  103. data/sig/lib/hearth/auth_schemes/http_basic.rbs +7 -0
  104. data/sig/lib/hearth/auth_schemes/http_bearer.rbs +7 -0
  105. data/sig/lib/hearth/auth_schemes/http_digest.rbs +7 -0
  106. data/sig/lib/hearth/auth_schemes.rbs +13 -0
  107. data/sig/lib/hearth/block_io.rbs +9 -0
  108. data/sig/lib/hearth/client.rbs +9 -0
  109. data/sig/lib/hearth/client_stubs.rbs +5 -0
  110. data/sig/lib/hearth/configuration.rbs +7 -0
  111. data/sig/lib/hearth/dns/host_address.rbs +11 -0
  112. data/sig/lib/hearth/dns/host_resolver.rbs +19 -0
  113. data/sig/lib/hearth/endpoint_rules.rbs +17 -0
  114. data/sig/lib/hearth/http/api_error.rbs +13 -0
  115. data/sig/lib/hearth/http/client.rbs +9 -0
  116. data/sig/lib/hearth/http/field.rbs +19 -0
  117. data/sig/lib/hearth/http/fields.rbs +43 -0
  118. data/sig/lib/hearth/http/header_list_builder.rbs +15 -0
  119. data/sig/lib/hearth/http/header_list_parser.rbs +19 -0
  120. data/sig/lib/hearth/http/networking_error.rbs +6 -0
  121. data/sig/lib/hearth/http/request.rbs +25 -0
  122. data/sig/lib/hearth/http/response.rbs +21 -0
  123. data/sig/lib/hearth/identities/anonymous.rbs +6 -0
  124. data/sig/lib/hearth/identities/http_api_key.rbs +9 -0
  125. data/sig/lib/hearth/identities/http_bearer.rbs +9 -0
  126. data/sig/lib/hearth/identities/http_login.rbs +11 -0
  127. data/sig/lib/hearth/identities.rbs +9 -0
  128. data/sig/lib/hearth/identity_provider.rbs +7 -0
  129. data/sig/lib/hearth/interceptor.rbs +9 -0
  130. data/sig/lib/hearth/interceptor_context.rbs +17 -0
  131. data/sig/lib/hearth/interceptor_list.rbs +16 -0
  132. data/sig/lib/hearth/interfaces.rbs +87 -0
  133. data/sig/lib/hearth/json/parse_error.rbs +9 -0
  134. data/sig/lib/hearth/networking_error.rbs +7 -0
  135. data/sig/lib/hearth/output.rbs +11 -0
  136. data/sig/lib/hearth/plugin_list.rbs +13 -0
  137. data/sig/lib/hearth/query/param.rbs +17 -0
  138. data/sig/lib/hearth/query/param_list.rbs +25 -0
  139. data/sig/lib/hearth/refreshing_identity_provider.rbs +10 -0
  140. data/sig/lib/hearth/request.rbs +9 -0
  141. data/sig/lib/hearth/response.rbs +11 -0
  142. data/sig/lib/hearth/retry/adaptive.rbs +13 -0
  143. data/sig/lib/hearth/retry/exponential_backoff.rbs +7 -0
  144. data/sig/lib/hearth/retry/standard.rbs +13 -0
  145. data/sig/lib/hearth/retry/strategy.rbs +11 -0
  146. data/sig/lib/hearth/retry.rbs +9 -0
  147. data/sig/lib/hearth/signers/anonymous.rbs +9 -0
  148. data/sig/lib/hearth/signers/http_api_key.rbs +9 -0
  149. data/sig/lib/hearth/signers/http_basic.rbs +9 -0
  150. data/sig/lib/hearth/signers/http_bearer.rbs +9 -0
  151. data/sig/lib/hearth/signers/http_digest.rbs +9 -0
  152. data/sig/lib/hearth/signers.rbs +9 -0
  153. data/sig/lib/hearth/structure.rbs +6 -0
  154. data/sig/lib/hearth/stubs.rbs +9 -0
  155. data/sig/lib/hearth/union.rbs +5 -0
  156. data/sig/lib/hearth/waiters/waiter.rbs +17 -0
  157. data/sig/lib/hearth/xml/parse_error.rbs +9 -0
  158. metadata +151 -25
  159. data/lib/hearth/http/headers.rb +0 -70
  160. data/lib/hearth/middleware/around_handler.rb +0 -24
  161. data/lib/hearth/middleware/request_handler.rb +0 -24
  162. data/lib/hearth/middleware/response_handler.rb +0 -25
  163. data/lib/hearth/middleware_builder.rb +0 -246
  164. data/lib/hearth/stubbing/client_stubs.rb +0 -115
  165. data/lib/hearth/stubbing/stubs.rb +0 -32
  166. data/lib/hearth/waiters/errors.rb +0 -15
  167. data/sig/lib/seahorse/api_error.rbs +0 -10
  168. data/sig/lib/seahorse/document.rbs +0 -2
  169. data/sig/lib/seahorse/http/api_error.rbs +0 -21
  170. data/sig/lib/seahorse/http/headers.rbs +0 -47
  171. data/sig/lib/seahorse/http/response.rbs +0 -21
  172. data/sig/lib/seahorse/simple_delegator.rbs +0 -3
  173. data/sig/lib/seahorse/structure.rbs +0 -18
  174. data/sig/lib/seahorse/stubbing/client_stubs.rbs +0 -103
  175. data/sig/lib/seahorse/stubbing/stubs.rbs +0 -14
  176. data/sig/lib/seahorse/union.rbs +0 -6
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'base64'
4
+
5
+ module Hearth
6
+ module Signers
7
+ # A signer that signs requests using the HTTP Basic Auth scheme.
8
+ class HTTPBasic
9
+ # rubocop:disable Lint/UnusedMethodArgument
10
+ def sign(request:, identity:, properties:)
11
+ # TODO: does not handle realm or other properties
12
+ identity_string = "#{identity.username}:#{identity.password}"
13
+ encoded = Base64.strict_encode64(identity_string)
14
+ request.headers['Authorization'] = "Basic #{encoded}"
15
+ end
16
+
17
+ def reset(request:, properties:)
18
+ request.headers.delete('Authorization')
19
+ end
20
+ # rubocop:enable Lint/UnusedMethodArgument
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hearth
4
+ module Signers
5
+ # A signer that signs requests using the HTTP Bearer Auth scheme.
6
+ class HTTPBearer < Signers::Base
7
+ # rubocop:disable Lint/UnusedMethodArgument
8
+ def sign(request:, identity:, properties:)
9
+ # TODO: does not handle realm or other properties
10
+ request.headers['Authorization'] = "Bearer #{identity.token}"
11
+ end
12
+
13
+ def reset(request:, properties:)
14
+ request.headers.delete('Authorization')
15
+ end
16
+ # rubocop:enable Lint/UnusedMethodArgument
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hearth
4
+ module Signers
5
+ # A signer that signs requests using the HTTP Digest Auth scheme.
6
+ class HTTPDigest < Signers::Base
7
+ def sign(request:, identity:, properties:)
8
+ # TODO: requires a nonce from the server - this cannot
9
+ # be implemented unless we rescue from a 401 and retry
10
+ # with the nonce
11
+ raise NotImplementedError
12
+ end
13
+
14
+ def reset(request:, properties:)
15
+ raise NotImplementedError
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hearth
4
+ # Namespace for all Signer classes.
5
+ module Signers
6
+ # Base class for all Signer classes.
7
+ class Base
8
+ def sign(request:, identity:, properties:)
9
+ raise NotImplementedError
10
+ end
11
+
12
+ def reset(request:, properties:)
13
+ raise NotImplementedError
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ require_relative 'signers/anonymous'
20
+ require_relative 'signers/http_api_key'
21
+ require_relative 'signers/http_basic'
22
+ require_relative 'signers/http_bearer'
23
+ require_relative 'signers/http_digest'
@@ -6,15 +6,15 @@ module Hearth
6
6
  # Deeply converts the Struct into a hash. Structure members that
7
7
  # are `nil` are omitted from the resultant hash.
8
8
  #
9
- # @return [Hash]
9
+ # @return [Hash, Structure]
10
10
  def to_h(obj = self)
11
11
  case obj
12
12
  when Struct
13
13
  _to_h_struct(obj)
14
14
  when Hash
15
15
  _to_h_hash(obj)
16
- when Array, Set
17
- obj.collect { |value| to_hash(value) }
16
+ when Array
17
+ _to_h_array(obj)
18
18
  when Union
19
19
  obj.to_h
20
20
  else
@@ -36,5 +36,9 @@ module Hearth
36
36
  hash[key] = to_hash(value)
37
37
  end
38
38
  end
39
+
40
+ def _to_h_array(obj)
41
+ obj.collect { |value| to_hash(value) }
42
+ end
39
43
  end
40
44
  end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hearth
4
+ # Provides a thread safe data structure for adding and getting stubs
5
+ # per operation.
6
+ class Stubs
7
+ # Initializes the stubs with an optional hash of stubs.
8
+ # For an example of stubs, see {ClientStubs}.
9
+ # @param [Hash<Symbol, Array<Stub>>] stubs
10
+ def initialize(stubs = {})
11
+ @stubs = stubs
12
+ @stub_mutex = Mutex.new
13
+ end
14
+
15
+ # Adds a stub or list of stubs to the given operation name.
16
+ # @param [String] operation_name
17
+ # @param [Array<Stub>] stubs
18
+ def set_stubs(operation_name, stubs)
19
+ @stub_mutex.synchronize do
20
+ @stubs[operation_name.to_sym] = stubs
21
+ end
22
+ end
23
+
24
+ # Returns the next stub for the given operation name.
25
+ # @param [String] operation_name
26
+ # @return [Stub, nil]
27
+ def next(operation_name)
28
+ @stub_mutex.synchronize do
29
+ stubs = @stubs[operation_name] || []
30
+ case stubs.length
31
+ when 0 then nil
32
+ when 1 then stubs.first
33
+ else stubs.shift
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -11,24 +11,25 @@ module Hearth
11
11
  # @param [Time] time
12
12
  # @return [String<Date Time>] The time as an ISO8601 string.
13
13
  def to_date_time(time)
14
- time.utc.strftime('%Y-%m-%dT%H:%M:%SZ')
14
+ optional_ms_digits = time.subsec.zero? ? nil : 3
15
+ time.utc.iso8601(optional_ms_digits)
15
16
  end
16
17
 
17
18
  # @param [Time] time
18
- # @return [Float<Epoch Seconds>] Returns float value of
19
+ # @return [Float<Epoch Seconds>] Returns the float value of
19
20
  # epoch seconds with millisecond precision.
20
21
  def to_epoch_seconds(time)
21
22
  time = time.utc
22
23
  epoch_seconds = time.to_i
23
- epoch_seconds += (time.nsec / 1_000_000) / 1000.0
24
- epoch_seconds
24
+ epoch_seconds + ((time.nsec / 1_000_000) / 1000.0)
25
25
  end
26
26
 
27
27
  # @param [Time] time
28
28
  # @return [String<Http Date>] Returns the time formatted
29
29
  # as an HTTP header date.
30
30
  def to_http_date(time)
31
- time.utc.httpdate
31
+ fractional = '.%L' unless time.subsec.zero?
32
+ time.utc.strftime("%a, %d %b %Y %H:%M:%S#{fractional} GMT")
32
33
  end
33
34
  end
34
35
  end
@@ -3,18 +3,73 @@
3
3
  module Hearth
4
4
  # Utility module for working with request parameters.
5
5
  #
6
- # * Validate structure of parameters against the expected type.
6
+ # * Validate structure of parameters against the expected input.
7
7
  # * Raise errors with context when validation fails.
8
8
  # @api private
9
9
  module Validator
10
- # Validate the given values is of the given type(s).
10
+ # Validate the given value is within the expected range (inclusive).
11
+ # @param value [Object] The value to validate.
12
+ # @param min [Numeric] The minimum that the given value should be.
13
+ # @param max [Numeric] The maximum that the given value should be.
14
+ # @param context [String] The context of the value being validated.
15
+ # @raise [ArgumentError] Raises when the value is not within expected range.
16
+ def self.validate_range!(value, min:, max:, context:)
17
+ return if value.nil? || value.between?(min, max)
18
+
19
+ raise ArgumentError,
20
+ "Expected #{context} to be between " \
21
+ "#{min} to #{max}, got #{value}."
22
+ end
23
+
24
+ # Validate the given value responds to the given methods.
25
+ # @param value [Object] The value to validate.
26
+ # @param methods [Array<Symbol>] The methods to validate against.
27
+ # @param context [String] The context of the value being validated.
28
+ # @raise [ArgumentError] Raises when the value does not respond to the
29
+ # methods.
30
+ def self.validate_responds_to!(value, *methods, context:)
31
+ if value.nil? || methods.all? { |method| value.respond_to?(method) }
32
+ return
33
+ end
34
+
35
+ raise ArgumentError,
36
+ "Expected #{context} to respond to " \
37
+ "[#{methods.map(&:to_s).join(', ')}], got #{value.class}."
38
+ end
39
+
40
+ # Validate a value is present and not nil.
41
+ # @param value [Object] The value to validate.
42
+ # @param context [String] The context of the value being validated.
43
+ # @raise [ArgumentError] Raises when the value is nil.
44
+ def self.validate_required!(value, context:)
45
+ raise ArgumentError, "Expected #{context} to be set." if value.nil?
46
+ end
47
+
48
+ # Validate the given value is of the given type(s).
49
+ # @param value [Object] The value to validate.
50
+ # @param types [Array<Class>] The types to validate against.
51
+ # @param context [String] The context of the value being validated.
11
52
  # @raise [ArgumentError] Raises when the value is not one of given type(s).
12
- def self.validate!(value, *types, context:)
13
- return if !value || types.any? { |type| value.is_a?(type) }
53
+ def self.validate_types!(value, *types, context:)
54
+ return if value.nil? || types.any? { |type| value.is_a?(type) }
14
55
 
15
56
  raise ArgumentError,
16
- "Expected #{context} to be in "\
57
+ "Expected #{context} to be in " \
17
58
  "[#{types.map(&:to_s).join(', ')}], got #{value.class}."
18
59
  end
60
+
61
+ # Validate unknown parameters are not present for a given Struct.
62
+ # @param struct [Struct] The Struct to validate against.
63
+ # @param params [Hash] The parameters to validate.
64
+ # @param context [String] The context of the value being validated.
65
+ # @raise [ArgumentError] Raises when unknown parameters are present.
66
+ def self.validate_unknown!(struct, params, context:)
67
+ unknown = params.keys - struct.members
68
+ return if unknown.empty?
69
+
70
+ unknown = unknown.map { |key| "#{context}[:#{key}]" }
71
+ raise ArgumentError,
72
+ "Unexpected members: [#{unknown.join(', ')}]"
73
+ end
19
74
  end
20
75
  end
@@ -6,8 +6,8 @@ module Hearth
6
6
  module Waiters
7
7
  # Abstract Poller used by generated service Waiters. This class handles
8
8
  # sending the request and matching input or output.
9
+ # @api private
9
10
  class Poller
10
- # @api private
11
11
  def initialize(options = {})
12
12
  @operation_name = options[:operation_name]
13
13
  @acceptors = options[:acceptors]
@@ -21,7 +21,7 @@ module Hearth
21
21
  # * `:retry` - The waiter may be retried.
22
22
  # * `:error` - The waiter encountered an un-expected error.
23
23
  #
24
- # @example A trival (bad) example of a waiter that polls indefinetly.
24
+ # @example A trivial (bad) example of a waiter that polls indefinitely.
25
25
  #
26
26
  # loop do
27
27
  #
@@ -39,10 +39,10 @@ module Hearth
39
39
  # @param [Client] client
40
40
  # @param [Hash] params
41
41
  # @param [Hash] options
42
- # @return [Array<Symbol,Response>]
42
+ # @return [Array<Symbol, Response, ApiError>]
43
43
  def call(client, params = {}, options = {})
44
44
  begin
45
- options = options.merge(input_output_middleware)
45
+ options = options.merge(input_output_interceptor)
46
46
  response = client.send(@operation_name, params, options)
47
47
  rescue Hearth::ApiError => e
48
48
  error = e
@@ -58,11 +58,10 @@ module Hearth
58
58
 
59
59
  private
60
60
 
61
- def input_output_middleware
62
- middleware = lambda do |input, _context|
63
- @input = input # get internal details of middleware
64
- end
65
- { middleware: MiddlewareBuilder.before_send(middleware) }
61
+ def input_output_interceptor
62
+ # get internal details - capture input before send
63
+ interceptor = proc { |context| @input = context.input }
64
+ { interceptors: [Interceptor.new(read_before_transmit: interceptor)] }
66
65
  end
67
66
 
68
67
  def acceptor_matches?(matcher, response, error)
@@ -82,6 +81,8 @@ module Hearth
82
81
  end
83
82
 
84
83
  def error_type_matcher?(matcher, error)
84
+ return false unless error
85
+
85
86
  # handle shape ID cases
86
87
  matcher = matcher.split('#').last.split('$').first
87
88
  error.class.to_s.include?(matcher) || error.error_code == matcher
@@ -2,9 +2,22 @@
2
2
 
3
3
  module Hearth
4
4
  module Waiters
5
+ # A super class error that is raised when a waiter detects a condition
6
+ # where the waiter can never succeed.
7
+ class WaiterFailed < StandardError; end
8
+
9
+ # Raised when the waiter reached an expected failure state.
10
+ class FailureStateError < WaiterFailed; end
11
+
12
+ # Raised when the waiter has reached the maximum waiting time.
13
+ class MaxWaitTimeExceededError < WaiterFailed; end
14
+
15
+ # Raised when the waiter received an unexpected error.
16
+ class UnexpectedError < WaiterFailed; end
17
+
5
18
  # Abstract waiter class with high level logic for polling and waiting.
19
+ # @api private
6
20
  class Waiter
7
- # @api private
8
21
  def initialize(options = {})
9
22
  unless options[:max_wait_time].is_a?(Integer)
10
23
  raise ArgumentError,
@@ -42,11 +55,11 @@ module Hearth
42
55
  case state
43
56
  when :retry then nil
44
57
  when :success then return
45
- when :failure then raise Errors::FailureStateError, resp_or_error
46
- when :error then raise Errors::UnexpectedError, resp_or_error
58
+ when :failure then raise FailureStateError, resp_or_error
59
+ when :error then raise UnexpectedError, resp_or_error
47
60
  end
48
61
 
49
- raise Errors::MaxWaitTimeExceeded if @one_more_retry
62
+ raise MaxWaitTimeExceededError if @one_more_retry
50
63
 
51
64
  delay = delay(n)
52
65
  @remaining_time -= delay
@@ -55,11 +68,12 @@ module Hearth
55
68
  end
56
69
 
57
70
  def delay(attempt)
58
- delay = if attempt > attempt_ceiling
59
- max_delay
60
- else
61
- min_delay * (2**(attempt - 1))
62
- end
71
+ delay =
72
+ if attempt > attempt_ceiling
73
+ max_delay
74
+ else
75
+ min_delay * (2**(attempt - 1))
76
+ end
63
77
 
64
78
  delay = Kernel.rand(min_delay..delay)
65
79
 
@@ -45,7 +45,7 @@ module Hearth
45
45
  end
46
46
 
47
47
  def text_node(node, pad)
48
- text = node.text.encode(xml: :text)
48
+ text = escape(node.text, :text)
49
49
  "#{pad}<#{node.name}#{attrs(node)}>#{text}</#{node.name}>#{@eol}"
50
50
  end
51
51
 
@@ -60,9 +60,18 @@ module Hearth
60
60
 
61
61
  def attrs(node)
62
62
  node.attributes.map do |key, value|
63
- " #{key}=#{value.to_s.encode(xml: :attr)}"
63
+ " #{key}=#{escape(value, :attr)}"
64
64
  end.join
65
65
  end
66
+
67
+ def escape(string, text_or_attr)
68
+ string.to_s
69
+ .encode(xml: text_or_attr)
70
+ .gsub("\u{000D}", '&#xD;') # Carriage Return
71
+ .gsub("\u{000A}", '&#xA;') # Line Feed
72
+ .gsub("\u{0085}", '&#x85;') # Next Line
73
+ .gsub("\u{2028}", '&#x2028;') # Line Separator
74
+ end
66
75
  end
67
76
  end
68
77
  end
@@ -5,13 +5,12 @@ module Hearth
5
5
  # A class used to represent an XML node.
6
6
  # @api private
7
7
  class Node
8
- # @api private
9
8
  BOTH_TYPES = 'Nodes may not have both text and child nodes'
10
9
 
11
10
  # @param [String] name
12
- def initialize(name, *children)
11
+ def initialize(name, *children, attributes: {})
13
12
  @name = name
14
- @attributes = {}
13
+ @attributes = attributes
15
14
  @child_nodes = []
16
15
  @child_node_map = {}
17
16
  @text = []
@@ -3,7 +3,6 @@
3
3
  require 'rspec/expectations'
4
4
 
5
5
  # Provides an rspec matcher for Hearth::XML::Node
6
- # @api private
7
6
  RSpec::Matchers.define :match_xml_node do |expected|
8
7
  match do |actual|
9
8
  return true if actual == expected
data/lib/hearth.rb CHANGED
@@ -1,22 +1,53 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'hearth/api_error'
4
+ require_relative 'hearth/auth_option'
5
+
6
+ # must be required before auth_schemes
7
+ require_relative 'hearth/identities'
8
+ require_relative 'hearth/auth_schemes'
9
+ require_relative 'hearth/anonymous_auth_resolver'
10
+
4
11
  require_relative 'hearth/block_io'
12
+ require_relative 'hearth/checksums'
13
+ require_relative 'hearth/client'
14
+ require_relative 'hearth/configuration'
15
+ require_relative 'hearth/config/env_provider'
16
+ require_relative 'hearth/config/resolver'
17
+ require_relative 'hearth/connection_pool'
5
18
  require_relative 'hearth/context'
19
+ require_relative 'hearth/dns'
20
+
21
+ # must be required before http
22
+ require_relative 'hearth/middleware'
23
+ require_relative 'hearth/networking_error'
24
+ require_relative 'hearth/request'
25
+ require_relative 'hearth/response'
26
+
27
+ # must be required before endpoint rules
28
+ require_relative 'hearth/structure'
29
+
30
+ require_relative 'hearth/endpoint_rules'
6
31
  require_relative 'hearth/http'
32
+ require_relative 'hearth/identity_provider'
33
+ require_relative 'hearth/interceptor'
34
+ require_relative 'hearth/interceptors'
35
+ require_relative 'hearth/interceptor_context'
36
+ require_relative 'hearth/interceptor_list'
7
37
  require_relative 'hearth/json'
8
- require_relative 'hearth/middleware'
9
- require_relative 'hearth/middleware_builder'
38
+ require_relative 'hearth/plugin_list'
10
39
  require_relative 'hearth/middleware_stack'
11
40
  require_relative 'hearth/number_helper'
12
41
  require_relative 'hearth/output'
13
- require_relative 'hearth/structure'
14
- require_relative 'hearth/stubbing/client_stubs'
15
- require_relative 'hearth/stubbing/stubs'
42
+ require_relative 'hearth/query/param'
43
+ require_relative 'hearth/query/param_list'
44
+ require_relative 'hearth/refreshing_identity_provider'
45
+ require_relative 'hearth/retry'
46
+ require_relative 'hearth/signers'
47
+ require_relative 'hearth/stubs'
16
48
  require_relative 'hearth/time_helper'
17
49
  require_relative 'hearth/union'
18
50
  require_relative 'hearth/validator'
19
- require_relative 'hearth/waiters/errors'
20
51
  require_relative 'hearth/waiters/poller'
21
52
  require_relative 'hearth/waiters/waiter'
22
53
  require_relative 'hearth/xml'
@@ -0,0 +1,6 @@
1
+ module Hearth
2
+ type document = Hash[Symbol, document] | Array[document] | String | bool | Numeric
3
+
4
+ type stub = Structure | Response | { data: Hash[Symbol, untyped] } |
5
+ { error: { class: Class, data: Hash[Symbol, untyped] } } | ApiError | Proc
6
+ end
@@ -0,0 +1,5 @@
1
+ module Hearth
2
+ class AnonymousAuthResolver
3
+ def resolve: -> ::Array[AuthOption]
4
+ end
5
+ end
@@ -0,0 +1,13 @@
1
+ module Hearth
2
+ class ApiError < StandardError
3
+ def initialize: (error_code: String, ?metadata: Hash[Symbol, untyped], ?message: String?) -> void
4
+
5
+ attr_reader error_code: String
6
+
7
+ attr_reader metadata: Hash[Symbol, untyped]
8
+
9
+ def retryable?: () -> false
10
+
11
+ def throttling?: () -> false
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ module Hearth
2
+ class AuthOption
3
+ def initialize: (scheme_id: String, ?identity_properties: Hash[Symbol, untyped], ?signer_properties: Hash[Symbol, untyped]) -> void
4
+
5
+ attr_reader scheme_id: String
6
+
7
+ attr_reader identity_properties: Hash[Symbol, untyped]
8
+
9
+ attr_reader signer_properties: Hash[Symbol, untyped]
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ module Hearth
2
+ module AuthSchemes
3
+ class Anonymous < AuthSchemes::Base
4
+ def initialize: () -> void
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Hearth
2
+ module AuthSchemes
3
+ class HTTPApiKey < AuthSchemes::Base
4
+ def initialize: () -> void
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Hearth
2
+ module AuthSchemes
3
+ class HTTPBasic < AuthSchemes::Base
4
+ def initialize: () -> void
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Hearth
2
+ module AuthSchemes
3
+ class HTTPBearer < AuthSchemes::Base
4
+ def initialize: () -> void
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Hearth
2
+ module AuthSchemes
3
+ class HTTPDigest < AuthSchemes::Base
4
+ def initialize: () -> void
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,13 @@
1
+ module Hearth
2
+ module AuthSchemes
3
+ class Base
4
+ def initialize: (scheme_id: String, signer: Signers::Base, identity_type: Class) -> void
5
+
6
+ attr_reader scheme_id: String
7
+
8
+ def identity_provider: (?Hash[Symbol, IdentityProvider] identity_providers) -> IdentityProvider
9
+
10
+ attr_reader signer: Signers::Base
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,9 @@
1
+ module Hearth
2
+ class BlockIO
3
+ def initialize: (Proc block) -> void
4
+
5
+ attr_reader bytes_yielded: Integer
6
+
7
+ def write: (String data) -> Integer
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Hearth
2
+ class Client
3
+ def initialize: (Hash[Symbol, untyped], Class) -> void
4
+
5
+ attr_reader config: untyped
6
+
7
+ def self.plugins: () -> PluginList[untyped]
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ module Hearth
2
+ module ClientStubs
3
+ def stub_responses: (Symbol operation_name, *stub stubs) -> void
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ module Hearth
2
+ module Configuration[ServiceConfig]
3
+ def initialize: (**Hash[Symbol, untyped] options) -> void
4
+
5
+ def merge: (Hash[Symbol, untyped] configuration) -> ServiceConfig
6
+ end
7
+ end
@@ -0,0 +1,11 @@
1
+ module Hearth
2
+ module DNS
3
+ class HostAddress < Struct[untyped]
4
+ attr_reader address_type: Symbol
5
+
6
+ attr_reader address: String
7
+
8
+ attr_reader hostname: String
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ module Hearth
2
+ module DNS
3
+ class HostResolver
4
+ def initialize: (?service: Integer, ?family: Integer?, ?socktype: Symbol, ?protocol: Integer?, ?flags: Integer?) -> void
5
+
6
+ attr_reader service: Integer
7
+
8
+ attr_reader family: Integer?
9
+
10
+ attr_reader socktype: Symbol
11
+
12
+ attr_reader protocol: Integer?
13
+
14
+ attr_reader flags: Integer?
15
+
16
+ def resolve_address: (nodename: String, ?service: Integer, ?family: Integer?, ?socktype: Symbol, ?protocol: Integer?, ?flags: Integer?) -> Array[HostAddress]
17
+ end
18
+ end
19
+ end