hearth 1.0.0.pre1 → 1.0.0.pre2

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.
Files changed (157) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -4
  3. data/VERSION +1 -1
  4. data/lib/hearth/api_error.rb +15 -1
  5. data/lib/hearth/auth_option.rb +21 -0
  6. data/lib/hearth/auth_schemes/anonymous.rb +21 -0
  7. data/lib/hearth/auth_schemes/http_api_key.rb +16 -0
  8. data/lib/hearth/auth_schemes/http_basic.rb +16 -0
  9. data/lib/hearth/auth_schemes/http_bearer.rb +16 -0
  10. data/lib/hearth/auth_schemes/http_digest.rb +16 -0
  11. data/lib/hearth/auth_schemes.rb +32 -0
  12. data/lib/hearth/checksums.rb +31 -0
  13. data/lib/hearth/client_stubs.rb +130 -0
  14. data/lib/hearth/config/env_provider.rb +53 -0
  15. data/lib/hearth/config/resolver.rb +52 -0
  16. data/lib/hearth/configuration.rb +15 -0
  17. data/lib/hearth/connection_pool.rb +77 -0
  18. data/lib/hearth/context.rb +28 -4
  19. data/lib/hearth/dns/host_address.rb +23 -0
  20. data/lib/hearth/dns/host_resolver.rb +92 -0
  21. data/lib/hearth/dns.rb +48 -0
  22. data/lib/hearth/http/api_error.rb +4 -8
  23. data/lib/hearth/http/client.rb +208 -59
  24. data/lib/hearth/http/error_inspector.rb +85 -0
  25. data/lib/hearth/http/error_parser.rb +18 -20
  26. data/lib/hearth/http/field.rb +64 -0
  27. data/lib/hearth/http/fields.rb +117 -0
  28. data/lib/hearth/http/middleware/content_length.rb +5 -2
  29. data/lib/hearth/http/middleware/content_md5.rb +31 -0
  30. data/lib/hearth/http/middleware/request_compression.rb +157 -0
  31. data/lib/hearth/http/middleware.rb +12 -0
  32. data/lib/hearth/http/networking_error.rb +1 -14
  33. data/lib/hearth/http/request.rb +83 -56
  34. data/lib/hearth/http/response.rb +42 -13
  35. data/lib/hearth/http.rb +14 -5
  36. data/lib/hearth/identities/anonymous.rb +8 -0
  37. data/lib/hearth/identities/http_api_key.rb +16 -0
  38. data/lib/hearth/identities/http_bearer.rb +16 -0
  39. data/lib/hearth/identities/http_login.rb +20 -0
  40. data/lib/hearth/identities.rb +21 -0
  41. data/lib/hearth/identity_resolver.rb +17 -0
  42. data/lib/hearth/interceptor.rb +506 -0
  43. data/lib/hearth/interceptor_context.rb +36 -0
  44. data/lib/hearth/interceptor_list.rb +48 -0
  45. data/lib/hearth/interceptors.rb +75 -0
  46. data/lib/hearth/middleware/auth.rb +100 -0
  47. data/lib/hearth/middleware/build.rb +32 -0
  48. data/lib/hearth/middleware/host_prefix.rb +10 -6
  49. data/lib/hearth/middleware/initialize.rb +58 -0
  50. data/lib/hearth/middleware/parse.rb +45 -6
  51. data/lib/hearth/middleware/retry.rb +97 -23
  52. data/lib/hearth/middleware/send.rb +137 -25
  53. data/lib/hearth/middleware/sign.rb +65 -0
  54. data/lib/hearth/middleware/validate.rb +11 -1
  55. data/lib/hearth/middleware.rb +19 -8
  56. data/lib/hearth/middleware_stack.rb +1 -43
  57. data/lib/hearth/networking_error.rb +18 -0
  58. data/lib/hearth/number_helper.rb +2 -2
  59. data/lib/hearth/output.rb +8 -4
  60. data/lib/hearth/plugin_list.rb +53 -0
  61. data/lib/hearth/query/param.rb +52 -0
  62. data/lib/hearth/query/param_list.rb +54 -0
  63. data/lib/hearth/query/param_matcher.rb +32 -0
  64. data/lib/hearth/refreshing_identity_resolver.rb +63 -0
  65. data/lib/hearth/request.rb +22 -0
  66. data/lib/hearth/response.rb +33 -0
  67. data/lib/hearth/retry/adaptive.rb +60 -0
  68. data/lib/hearth/retry/capacity_not_available_error.rb +9 -0
  69. data/lib/hearth/retry/client_rate_limiter.rb +143 -0
  70. data/lib/hearth/retry/exponential_backoff.rb +15 -0
  71. data/lib/hearth/retry/retry_quota.rb +56 -0
  72. data/lib/hearth/retry/standard.rb +46 -0
  73. data/lib/hearth/retry/strategy.rb +20 -0
  74. data/lib/hearth/retry.rb +16 -0
  75. data/lib/hearth/signers/anonymous.rb +16 -0
  76. data/lib/hearth/signers/http_api_key.rb +29 -0
  77. data/lib/hearth/signers/http_basic.rb +23 -0
  78. data/lib/hearth/signers/http_bearer.rb +19 -0
  79. data/lib/hearth/signers/http_digest.rb +19 -0
  80. data/lib/hearth/signers.rb +23 -0
  81. data/lib/hearth/stubs.rb +30 -0
  82. data/lib/hearth/time_helper.rb +5 -3
  83. data/lib/hearth/validator.rb +44 -5
  84. data/lib/hearth/waiters/poller.rb +6 -7
  85. data/lib/hearth/waiters/waiter.rb +17 -4
  86. data/lib/hearth/xml/formatter.rb +11 -2
  87. data/lib/hearth/xml/node.rb +2 -2
  88. data/lib/hearth.rb +32 -5
  89. data/sig/lib/hearth/aliases.rbs +4 -0
  90. data/sig/lib/hearth/api_error.rbs +13 -0
  91. data/sig/lib/hearth/auth_option.rbs +11 -0
  92. data/sig/lib/hearth/auth_schemes/anonymous.rbs +7 -0
  93. data/sig/lib/hearth/auth_schemes/http_api_key.rbs +7 -0
  94. data/sig/lib/hearth/auth_schemes/http_basic.rbs +7 -0
  95. data/sig/lib/hearth/auth_schemes/http_bearer.rbs +7 -0
  96. data/sig/lib/hearth/auth_schemes/http_digest.rbs +7 -0
  97. data/sig/lib/hearth/auth_schemes.rbs +13 -0
  98. data/sig/lib/hearth/block_io.rbs +9 -0
  99. data/sig/lib/hearth/client_stubs.rbs +5 -0
  100. data/sig/lib/hearth/configuration.rbs +7 -0
  101. data/sig/lib/hearth/dns/host_address.rbs +13 -0
  102. data/sig/lib/hearth/dns/host_resolver.rbs +19 -0
  103. data/sig/lib/hearth/http/api_error.rbs +13 -0
  104. data/sig/lib/hearth/http/client.rbs +9 -0
  105. data/sig/lib/hearth/http/field.rbs +19 -0
  106. data/sig/lib/hearth/http/fields.rbs +43 -0
  107. data/sig/lib/hearth/http/request.rbs +25 -0
  108. data/sig/lib/hearth/http/response.rbs +21 -0
  109. data/sig/lib/hearth/identities/anonymous.rbs +6 -0
  110. data/sig/lib/hearth/identities/http_api_key.rbs +9 -0
  111. data/sig/lib/hearth/identities/http_bearer.rbs +9 -0
  112. data/sig/lib/hearth/identities/http_login.rbs +11 -0
  113. data/sig/lib/hearth/identities.rbs +9 -0
  114. data/sig/lib/hearth/identity_resolver.rbs +7 -0
  115. data/sig/lib/hearth/interceptor.rbs +9 -0
  116. data/sig/lib/hearth/interceptor_context.rbs +15 -0
  117. data/sig/lib/hearth/interceptor_list.rbs +16 -0
  118. data/sig/lib/hearth/interfaces.rbs +65 -0
  119. data/sig/lib/hearth/output.rbs +11 -0
  120. data/sig/lib/hearth/plugin_list.rbs +15 -0
  121. data/sig/lib/hearth/query/param.rbs +17 -0
  122. data/sig/lib/hearth/query/param_list.rbs +25 -0
  123. data/sig/lib/hearth/request.rbs +9 -0
  124. data/sig/lib/hearth/response.rbs +11 -0
  125. data/sig/lib/hearth/retry/adaptive.rbs +13 -0
  126. data/sig/lib/hearth/retry/exponential_backoff.rbs +7 -0
  127. data/sig/lib/hearth/retry/standard.rbs +13 -0
  128. data/sig/lib/hearth/retry/strategy.rbs +11 -0
  129. data/sig/lib/hearth/retry.rbs +9 -0
  130. data/sig/lib/hearth/signers/anonymous.rbs +9 -0
  131. data/sig/lib/hearth/signers/http_api_key.rbs +9 -0
  132. data/sig/lib/hearth/signers/http_basic.rbs +9 -0
  133. data/sig/lib/hearth/signers/http_bearer.rbs +9 -0
  134. data/sig/lib/hearth/signers/http_digest.rbs +9 -0
  135. data/sig/lib/hearth/signers.rbs +9 -0
  136. data/sig/lib/hearth/structure.rbs +7 -0
  137. data/sig/lib/hearth/union.rbs +5 -0
  138. data/sig/lib/hearth/waiters/waiter.rbs +17 -0
  139. metadata +132 -22
  140. data/lib/hearth/http/headers.rb +0 -70
  141. data/lib/hearth/middleware/around_handler.rb +0 -24
  142. data/lib/hearth/middleware/request_handler.rb +0 -24
  143. data/lib/hearth/middleware/response_handler.rb +0 -25
  144. data/lib/hearth/middleware_builder.rb +0 -246
  145. data/lib/hearth/stubbing/client_stubs.rb +0 -115
  146. data/lib/hearth/stubbing/stubs.rb +0 -32
  147. data/lib/hearth/waiters/errors.rb +0 -15
  148. data/sig/lib/seahorse/api_error.rbs +0 -10
  149. data/sig/lib/seahorse/document.rbs +0 -2
  150. data/sig/lib/seahorse/http/api_error.rbs +0 -21
  151. data/sig/lib/seahorse/http/headers.rbs +0 -47
  152. data/sig/lib/seahorse/http/response.rbs +0 -21
  153. data/sig/lib/seahorse/simple_delegator.rbs +0 -3
  154. data/sig/lib/seahorse/structure.rbs +0 -18
  155. data/sig/lib/seahorse/stubbing/client_stubs.rbs +0 -103
  156. data/sig/lib/seahorse/stubbing/stubs.rbs +0 -14
  157. data/sig/lib/seahorse/union.rbs +0 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b43b47b8abef04f52e1f151032c376b90b3112e23c3084fbba6dd777e3f95180
4
- data.tar.gz: a902f668849d1c28d0afd66ce2c3b80eac6a5626187e3c44a1d13d99234576e0
3
+ metadata.gz: bace852980aa4785929fce82aeb1a0b683fd6cf1f77d83d1dee39315d8177361
4
+ data.tar.gz: bff4b301d6940ccb485973b728b761e0d773489068cb093bf1789fcfe8cd1c35
5
5
  SHA512:
6
- metadata.gz: 4958477705f77ead625d1bbb49b2c11b0e44542af63bf9aaa95d87bba82a73cdbed65b40461f56e6bc9388cb612cf4cb4c341e7ba1a9b2502076ffa809e3cf14
7
- data.tar.gz: 44f0d91c07b0f431b9660f459307daebbbbe8824ad90b4009cfdff63fa139c340201ed88667f80909bbd973bdc40216c74efd4601ce9fbbfb5d3c81e2f2bed2d
6
+ metadata.gz: 27e9e5a1c32430314c3df34e843efef873231e5691d4d7df262615e4a9b65fb1f29dbdf8c0b4037e2a86d13d7597e2ff29b45d8eea8db87b2ed1559740b4c53c
7
+ data.tar.gz: ae6db7148e7cc6b98d8a2d0cc0bab09327ff10774c78e5b3fd76ef8a219ac07ebff636fd7636c7c17ed53f3fcbf964ce111a8e3d11d090120d59f95d2eafb227
data/CHANGELOG.md CHANGED
@@ -1,12 +1,12 @@
1
1
  Unreleased Changes
2
2
  ------------------
3
3
 
4
- 1.0.0.pre1 (2022-01-10)
4
+ 1.0.0.pre2 (2023-12-19)
5
5
  ------------------
6
6
 
7
- * Feature - Initial public pre-release for Smithy Ruby SDKs.
7
+ * Feature - Second initial public pre-release for Smithy Ruby SDKs.
8
8
 
9
- 0.1.0 (2013-29-04)
9
+ 1.0.0.pre1 (2022-01-10)
10
10
  ------------------
11
11
 
12
- Not intended for public usage. Used as an internal detail of AWS SDK For Ruby v2 and v3.
12
+ * Feature - Initial public pre-release for Smithy Ruby SDKs.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.0.pre1
1
+ 1.0.0.pre2
@@ -4,12 +4,26 @@ module Hearth
4
4
  # Base class for errors returned from an API. This excludes networking
5
5
  # errors and errors generated on the client-side.
6
6
  class ApiError < StandardError
7
- def initialize(error_code:, message: nil)
7
+ def initialize(error_code:, metadata: {}, message: nil)
8
8
  @error_code = error_code
9
+ @metadata = metadata
9
10
  super(message)
10
11
  end
11
12
 
12
13
  # @return [String]
13
14
  attr_reader :error_code
15
+
16
+ # @return [Hash]
17
+ attr_reader :metadata
18
+
19
+ # @return [Boolean]
20
+ def retryable?
21
+ false
22
+ end
23
+
24
+ # @return [Boolean]
25
+ def throttling?
26
+ false
27
+ end
14
28
  end
15
29
  end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hearth
4
+ # Object that represents an auth option, returned by Auth Resolvers.
5
+ class AuthOption
6
+ def initialize(scheme_id:, identity_properties: {}, signer_properties: {})
7
+ @scheme_id = scheme_id
8
+ @identity_properties = identity_properties
9
+ @signer_properties = signer_properties
10
+ end
11
+
12
+ # @return [String]
13
+ attr_reader :scheme_id
14
+
15
+ # @return [Hash]
16
+ attr_reader :identity_properties
17
+
18
+ # @return [Hash]
19
+ attr_reader :signer_properties
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hearth
4
+ module AuthSchemes
5
+ # Anonymous authentication scheme.
6
+ class Anonymous < AuthSchemes::Base
7
+ def initialize
8
+ super(
9
+ scheme_id: 'smithy.api#noAuth',
10
+ signer: Signers::Anonymous.new,
11
+ identity_type: Identities::Anonymous
12
+ )
13
+ end
14
+
15
+ # @return [IdentityResolver, nil]
16
+ def identity_resolver(_identity_resolvers = {})
17
+ Hearth::IdentityResolver.new(proc { Identities::Anonymous.new })
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hearth
4
+ module AuthSchemes
5
+ # HTTP API Key authentication scheme.
6
+ class HTTPApiKey < AuthSchemes::Base
7
+ def initialize
8
+ super(
9
+ scheme_id: 'smithy.api#httpApiKeyAuth',
10
+ signer: Signers::HTTPApiKey.new,
11
+ identity_type: Identities::HTTPApiKey
12
+ )
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hearth
4
+ module AuthSchemes
5
+ # HTTP Basic authentication scheme.
6
+ class HTTPBasic < AuthSchemes::Base
7
+ def initialize
8
+ super(
9
+ scheme_id: 'smithy.api#httpBasicAuth',
10
+ signer: Signers::HTTPBasic.new,
11
+ identity_type: Identities::HTTPLogin
12
+ )
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hearth
4
+ module AuthSchemes
5
+ # HTTP Bearer authentication scheme.
6
+ class HTTPBearer < AuthSchemes::Base
7
+ def initialize
8
+ super(
9
+ scheme_id: 'smithy.api#httpBearerAuth',
10
+ signer: Signers::HTTPBearer.new,
11
+ identity_type: Identities::HTTPBearer
12
+ )
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hearth
4
+ module AuthSchemes
5
+ # HTTP Digest authentication scheme.
6
+ class HTTPDigest < AuthSchemes::Base
7
+ def initialize
8
+ super(
9
+ scheme_id: 'smithy.api#httpDigestAuth',
10
+ signer: Signers::HTTPDigest.new,
11
+ identity_type: Identities::HTTPLogin
12
+ )
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hearth
4
+ # Namespace for all AuthScheme classes.
5
+ module AuthSchemes
6
+ # Base class for all AuthScheme classes.
7
+ class Base
8
+ def initialize(scheme_id:, signer:, identity_type:)
9
+ @scheme_id = scheme_id
10
+ @signer = signer
11
+ @identity_type = identity_type
12
+ end
13
+
14
+ # @return [String]
15
+ attr_reader :scheme_id
16
+
17
+ # @return [IdentityResolver, nil]
18
+ def identity_resolver(identity_resolvers = {})
19
+ identity_resolvers[@identity_type]
20
+ end
21
+
22
+ # @return [Signers::Base]
23
+ attr_reader :signer
24
+ end
25
+ end
26
+ end
27
+
28
+ require_relative 'auth_schemes/anonymous'
29
+ require_relative 'auth_schemes/http_api_key'
30
+ require_relative 'auth_schemes/http_basic'
31
+ require_relative 'auth_schemes/http_bearer'
32
+ require_relative 'auth_schemes/http_digest'
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tempfile'
4
+
5
+ module Hearth
6
+ # A utility module for calculating checksums.
7
+ # @api private
8
+ module Checksums
9
+ CHUNK_SIZE = 1 * 1024 * 1024 # one MB
10
+
11
+ # @param [File, Tempfile, StringIO#read, String] value
12
+ # @return [String<MD5>]
13
+ def self.md5(value)
14
+ if value.is_a?(File) || value.is_a?(Tempfile)
15
+ OpenSSL::Digest.new('MD5').file(value).base64digest
16
+ elsif value.respond_to?(:read)
17
+ md5 = OpenSSL::Digest.new('MD5')
18
+ loop do
19
+ chunk = value.read(CHUNK_SIZE)
20
+ break unless chunk
21
+
22
+ md5.update(chunk)
23
+ end
24
+ value.rewind
25
+ md5.base64digest
26
+ else
27
+ OpenSSL::Digest.new('MD5').base64digest(value)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'stubs'
4
+
5
+ module Hearth
6
+ # This module provides the ability to specify the data and/or errors to
7
+ # return when a client is using stubbed responses.
8
+ # This module should be included in generated service clients.
9
+ #
10
+ # Pass `stub_responses: true` to a Client's Config constructor
11
+ # to enable this behavior.
12
+ module ClientStubs
13
+ # Configures what data / errors should be returned from the named operation
14
+ # when response stubbing is enabled.
15
+ #
16
+ # ## Basic usage
17
+ #
18
+ # When you enable response stubbing, the client will generate fake
19
+ # responses and will not make any HTTP requests. The SDK will default
20
+ # to generate fake responses with placeholder values. You can override
21
+ # the data returned using {#stub_responses}. You can also specify errors
22
+ # (with error data) that it should raise.
23
+ #
24
+ # client = Service::Client.new(stub_responses: true)
25
+ # client.operation
26
+ # #=> #<struct Service:Types::Operation param1=[], param2=nil>
27
+ #
28
+ # You can specify the modeled stub data using the :data key.
29
+ #
30
+ # client = Service::Client.new(stub_responses: true)
31
+ # client.stub_responses(
32
+ # :operation,
33
+ # data: { param1: [{ name: 'value1' }] }
34
+ # )
35
+ # client.operation.param1.map(&:name)
36
+ # #=> ['value1']
37
+ #
38
+ # Stub data can also be provided as an output Type.
39
+ #
40
+ # client = Service::Client.new(stub_responses: true)
41
+ # output = Service::Types::OperationOutput.new(
42
+ # param1: [{ name: 'value1' }]
43
+ # )
44
+ # client.stub_responses(:operation, output)
45
+ # client.operation(param1: 'value')
46
+ # #=> #<struct Service:Types::OperationOutput ..>
47
+ #
48
+ # You can also specify modeled errors or exceptions it should raise using
49
+ # the :error key. The error hash must have a :class and optionally any
50
+ # :data to populate the error with.
51
+ #
52
+ # client = Service::Client.new(stub_responses: true)
53
+ # client.stub_responses(
54
+ # :operation,
55
+ # error: { class: ModeledError, data: { message: 'error message' } }
56
+ # )
57
+ # #=> raises ModeledError.new('error message')
58
+ #
59
+ # Constructed Exceptions will also be raised if provided.
60
+ #
61
+ # client.stub_responses(:operation, Hearth::NetworkingError.new)
62
+ # client.operation(param1: 'value')
63
+ # #=> raises Hearth::NetworkingError
64
+ #
65
+ # ## Dynamic Stubbing
66
+ #
67
+ # In addition to creating static stubs, it's also possible to generate
68
+ # stubs dynamically based on the input with which operations were
69
+ # called, by passing a `Proc` object:
70
+ #
71
+ # client.stub_responses(:operation, -> (input) {
72
+ # if input[:param] == 'foo'
73
+ # # return a data stub
74
+ # { data: { param1: [{ name: 'value1'}]} }
75
+ # else
76
+ # # return an error stub
77
+ # { error: Service::Errors::NotFound }
78
+ # end
79
+ # })
80
+ #
81
+ # ## Stubbing Raw Protocol Responses
82
+ #
83
+ # As an alternative to providing the response data, you can provide an
84
+ # instance of Hearth::Response to stub with.
85
+ #
86
+ # response = Hearth::HTTP::Response.new(
87
+ # status: 200,
88
+ # body: StringIO.new('{param1: "value1"}'),
89
+ # )
90
+ # client.stub_responses(:operation, response)
91
+ # #=> #<struct Service:Types::OperationOutput param1="value1">
92
+ #
93
+ # ## Stubbing Multiple Responses
94
+ #
95
+ # Calling an operation multiple times will return similar responses.
96
+ # You can configure multiple stubs and they will be returned in sequence.
97
+ #
98
+ # client.stub_responses(
99
+ # :operation,
100
+ # { error: Service::Errors::NotFound },
101
+ # { data: { content_length: 150 } },
102
+ # ])
103
+ #
104
+ # client.operation(param1: 'value1')
105
+ # #=> raises Service::Errors::NotFound
106
+ #
107
+ # resp = client.operation(param1: 'value2')
108
+ # resp.data.content_length #=> 150
109
+ #
110
+ # @param [Symbol] operation_name
111
+ #
112
+ # @param [Mixed] stubs One or more responses to return from the named
113
+ # operation.
114
+ #
115
+ # @return [void]
116
+ #
117
+ # @raise [RuntimeError] Raises a runtime error when called
118
+ # on a client that has not enabled response stubbing via
119
+ # `:stub_responses => true`.
120
+ def stub_responses(operation_name, *stubs)
121
+ if @config.stub_responses
122
+ @stubs.add_stubs(operation_name, stubs.flatten)
123
+ else
124
+ msg = 'Stubbing is not enabled. Enable stubbing in Config ' \
125
+ 'with `stub_responses: true`'
126
+ raise ArgumentError, msg
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hearth
4
+ # @api private
5
+ module Config
6
+ # Parses and validates values provided in ENV
7
+ class EnvProvider
8
+ def initialize(env_key, type: 'String')
9
+ @env_key = env_key
10
+ @type = type
11
+ end
12
+
13
+ def call(_cfg)
14
+ return unless (value = ENV.fetch(@env_key, nil))
15
+
16
+ case @type
17
+ when 'Float' then parse_float(value)
18
+ when 'Integer' then parse_integer(value)
19
+ when 'Boolean' then parse_boolean(value)
20
+ else
21
+ value
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def parse_float(value)
28
+ Float(value)
29
+ rescue ArgumentError
30
+ raise_error(value)
31
+ end
32
+
33
+ def parse_integer(value)
34
+ Integer(value)
35
+ rescue ArgumentError
36
+ raise_error(value)
37
+ end
38
+
39
+ def parse_boolean(value)
40
+ case value.downcase
41
+ when 'true' then true
42
+ when 'false' then false
43
+ else raise_error(value)
44
+ end
45
+ end
46
+
47
+ def raise_error(value)
48
+ raise ArgumentError,
49
+ "Expected ENV['#{@env_key}'] to be a #{@type}, got #{value}."
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hearth
4
+ # @api private
5
+ module Config
6
+ # Resolves configuration options.
7
+ class Resolver
8
+ private_class_method :new
9
+
10
+ # @param config [Struct]
11
+ # @param options [Hash]
12
+ # @param defaults [Hash<Array<Proc>>]
13
+ # @return [Struct]
14
+ def self.resolve(config, options, defaults = {})
15
+ new(config).send(:resolve, options, defaults)
16
+ end
17
+
18
+ def key(key)
19
+ @options[key] = resolve_default(key) unless @options.key?(key)
20
+ @options[key]
21
+ end
22
+ alias [] key
23
+
24
+ private
25
+
26
+ # @param config [Struct]
27
+ def initialize(config)
28
+ @config = config
29
+ end
30
+
31
+ def resolve(options, defaults)
32
+ @options = options
33
+ @defaults = defaults
34
+ @config.members.each do |key|
35
+ @config[key] = key(key)
36
+ end
37
+ end
38
+
39
+ def resolve_default(key)
40
+ @defaults[key]&.each do |default|
41
+ value = if default.respond_to?(:call)
42
+ default.call(self)
43
+ else
44
+ default
45
+ end
46
+ return value unless value.nil?
47
+ end
48
+ nil
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hearth
4
+ # A module mixed into Config structs that resolves default value providers.
5
+ module Configuration
6
+ def initialize(**options)
7
+ Hearth::Config::Resolver.resolve(self, options, defaults)
8
+ super
9
+ end
10
+
11
+ def merge(configuration)
12
+ self.class.new(**to_h.merge(configuration.to_h))
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hearth
4
+ # @api private
5
+ class ConnectionPool
6
+ @pools_mutex = Mutex.new
7
+ @pools = {}
8
+
9
+ class << self
10
+ # @return [ConnectionPool]
11
+ def for(config = {})
12
+ @pools_mutex.synchronize do
13
+ @pools[config] ||= new
14
+ end
15
+ end
16
+
17
+ # @return [Array<ConnectionPool>] Returns a list of the
18
+ # constructed connection pools.
19
+ def pools
20
+ @pools_mutex.synchronize do
21
+ @pools.values
22
+ end
23
+ end
24
+ end
25
+
26
+ # @api private
27
+ def initialize
28
+ @pool_mutex = Mutex.new
29
+ @pool = {}
30
+ end
31
+
32
+ # @param [URI::HTTP, URI::HTTPS] endpoint The HTTP(S) endpoint
33
+ # to connect to (e.g. 'https://domain.com').
34
+ # @param [Proc] block A block that returns a new connection if
35
+ # there are no connections present.
36
+ # @return [Connection, nil]
37
+ def connection_for(endpoint, &block)
38
+ connection = nil
39
+ endpoint = remove_path_and_query(endpoint)
40
+ # attempt to recycle an already open connection
41
+ @pool_mutex.synchronize do
42
+ clean
43
+ connection = @pool[endpoint].shift if @pool.key?(endpoint)
44
+ end
45
+ connection || (block.call if block_given?)
46
+ end
47
+
48
+ # @param [URI::HTTP, URI::HTTPS] endpoint The HTTP(S) endpoint
49
+ # @param [Object] connection The connection to check back into the pool.
50
+ # @return [nil]
51
+ def offer(endpoint, connection)
52
+ endpoint = remove_path_and_query(endpoint)
53
+ @pool_mutex.synchronize do
54
+ @pool[endpoint] = [] unless @pool.key?(endpoint)
55
+ @pool[endpoint] << connection
56
+ end
57
+ end
58
+
59
+ private
60
+
61
+ # Removes stale connections from the pool. This method *must* be called
62
+ # @note **Must** be called behind a `@pool_mutex` synchronize block.
63
+ def clean
64
+ @pool.each_pair do |_endpoint, connections|
65
+ connections.delete_if(&:stale?)
66
+ end
67
+ end
68
+
69
+ # Connection pools should be keyed by endpoint and port.
70
+ def remove_path_and_query(endpoint)
71
+ endpoint.dup.tap do |e|
72
+ e.path = ''
73
+ e.query = nil
74
+ end.to_s
75
+ end
76
+ end
77
+ end
@@ -1,19 +1,26 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'securerandom'
4
+
3
5
  module Hearth
4
6
  # Stores request and response objects, and other useful things used by
5
7
  # multiple Middleware.
8
+ # @api private
6
9
  class Context
7
10
  def initialize(options = {})
11
+ @invocation_id = SecureRandom.uuid
8
12
  @operation_name = options[:operation_name]
9
13
  @request = options[:request]
10
14
  @response = options[:response]
11
15
  @logger = options[:logger]
12
- @params = options[:params]
16
+ @interceptors = options[:interceptors] || InterceptorList.new
13
17
  @metadata = options[:metadata] || {}
14
18
  end
15
19
 
16
- # @return [Symbol] Name of the API operation called.
20
+ # @return [String] The invocation ID for the request.
21
+ attr_reader :invocation_id
22
+
23
+ # @return [Symbol] The name of the API operation called.
17
24
  attr_reader :operation_name
18
25
 
19
26
  # @return [Hearth::HTTP::Request]
@@ -25,10 +32,27 @@ module Hearth
25
32
  # @return [Logger] An instance of the logger configured for the Client.
26
33
  attr_reader :logger
27
34
 
28
- # @return [Hash] The hash of the original request parameters.
29
- attr_reader :params
35
+ # @return [Array] An ordered list of interceptors
36
+ attr_reader :interceptors
37
+
38
+ # @return [ResolvedAuth, nil] The resolved auth for the request.
39
+ attr_accessor :auth
30
40
 
31
41
  # @return [Hash]
32
42
  attr_reader :metadata
43
+
44
+ # Returns the metadata for the given `key`.
45
+ # @param [Symbol] key
46
+ # @return [Object]
47
+ def [](key)
48
+ @metadata[key]
49
+ end
50
+
51
+ # Sets metadata for the given `key`.
52
+ # @param [Symbol] key
53
+ # @param [Object] value
54
+ def []=(key, value)
55
+ @metadata[key] = value
56
+ end
33
57
  end
34
58
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hearth
4
+ module DNS
5
+ # Address results from a DNS lookup in {HostResolver}.
6
+ class HostAddress
7
+ def initialize(address_type:, address:, hostname:)
8
+ @address_type = address_type
9
+ @address = address
10
+ @hostname = hostname
11
+ end
12
+
13
+ # @return [Symbol]
14
+ attr_reader :address_type
15
+
16
+ # @return [String]
17
+ attr_reader :address
18
+
19
+ # @return [String]
20
+ attr_reader :hostname
21
+ end
22
+ end
23
+ end