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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -4
- data/VERSION +1 -1
- data/lib/hearth/api_error.rb +15 -1
- data/lib/hearth/auth_option.rb +21 -0
- data/lib/hearth/auth_schemes/anonymous.rb +21 -0
- data/lib/hearth/auth_schemes/http_api_key.rb +16 -0
- data/lib/hearth/auth_schemes/http_basic.rb +16 -0
- data/lib/hearth/auth_schemes/http_bearer.rb +16 -0
- data/lib/hearth/auth_schemes/http_digest.rb +16 -0
- data/lib/hearth/auth_schemes.rb +32 -0
- data/lib/hearth/checksums.rb +31 -0
- data/lib/hearth/client_stubs.rb +130 -0
- data/lib/hearth/config/env_provider.rb +53 -0
- data/lib/hearth/config/resolver.rb +52 -0
- data/lib/hearth/configuration.rb +15 -0
- data/lib/hearth/connection_pool.rb +77 -0
- data/lib/hearth/context.rb +28 -4
- data/lib/hearth/dns/host_address.rb +23 -0
- data/lib/hearth/dns/host_resolver.rb +92 -0
- data/lib/hearth/dns.rb +48 -0
- data/lib/hearth/http/api_error.rb +4 -8
- data/lib/hearth/http/client.rb +208 -59
- data/lib/hearth/http/error_inspector.rb +85 -0
- data/lib/hearth/http/error_parser.rb +18 -20
- data/lib/hearth/http/field.rb +64 -0
- data/lib/hearth/http/fields.rb +117 -0
- data/lib/hearth/http/middleware/content_length.rb +5 -2
- data/lib/hearth/http/middleware/content_md5.rb +31 -0
- data/lib/hearth/http/middleware/request_compression.rb +157 -0
- data/lib/hearth/http/middleware.rb +12 -0
- data/lib/hearth/http/networking_error.rb +1 -14
- data/lib/hearth/http/request.rb +83 -56
- data/lib/hearth/http/response.rb +42 -13
- data/lib/hearth/http.rb +14 -5
- data/lib/hearth/identities/anonymous.rb +8 -0
- data/lib/hearth/identities/http_api_key.rb +16 -0
- data/lib/hearth/identities/http_bearer.rb +16 -0
- data/lib/hearth/identities/http_login.rb +20 -0
- data/lib/hearth/identities.rb +21 -0
- data/lib/hearth/identity_resolver.rb +17 -0
- data/lib/hearth/interceptor.rb +506 -0
- data/lib/hearth/interceptor_context.rb +36 -0
- data/lib/hearth/interceptor_list.rb +48 -0
- data/lib/hearth/interceptors.rb +75 -0
- data/lib/hearth/middleware/auth.rb +100 -0
- data/lib/hearth/middleware/build.rb +32 -0
- data/lib/hearth/middleware/host_prefix.rb +10 -6
- data/lib/hearth/middleware/initialize.rb +58 -0
- data/lib/hearth/middleware/parse.rb +45 -6
- data/lib/hearth/middleware/retry.rb +97 -23
- data/lib/hearth/middleware/send.rb +137 -25
- data/lib/hearth/middleware/sign.rb +65 -0
- data/lib/hearth/middleware/validate.rb +11 -1
- data/lib/hearth/middleware.rb +19 -8
- data/lib/hearth/middleware_stack.rb +1 -43
- data/lib/hearth/networking_error.rb +18 -0
- data/lib/hearth/number_helper.rb +2 -2
- data/lib/hearth/output.rb +8 -4
- data/lib/hearth/plugin_list.rb +53 -0
- data/lib/hearth/query/param.rb +52 -0
- data/lib/hearth/query/param_list.rb +54 -0
- data/lib/hearth/query/param_matcher.rb +32 -0
- data/lib/hearth/refreshing_identity_resolver.rb +63 -0
- data/lib/hearth/request.rb +22 -0
- data/lib/hearth/response.rb +33 -0
- data/lib/hearth/retry/adaptive.rb +60 -0
- data/lib/hearth/retry/capacity_not_available_error.rb +9 -0
- data/lib/hearth/retry/client_rate_limiter.rb +143 -0
- data/lib/hearth/retry/exponential_backoff.rb +15 -0
- data/lib/hearth/retry/retry_quota.rb +56 -0
- data/lib/hearth/retry/standard.rb +46 -0
- data/lib/hearth/retry/strategy.rb +20 -0
- data/lib/hearth/retry.rb +16 -0
- data/lib/hearth/signers/anonymous.rb +16 -0
- data/lib/hearth/signers/http_api_key.rb +29 -0
- data/lib/hearth/signers/http_basic.rb +23 -0
- data/lib/hearth/signers/http_bearer.rb +19 -0
- data/lib/hearth/signers/http_digest.rb +19 -0
- data/lib/hearth/signers.rb +23 -0
- data/lib/hearth/stubs.rb +30 -0
- data/lib/hearth/time_helper.rb +5 -3
- data/lib/hearth/validator.rb +44 -5
- data/lib/hearth/waiters/poller.rb +6 -7
- data/lib/hearth/waiters/waiter.rb +17 -4
- data/lib/hearth/xml/formatter.rb +11 -2
- data/lib/hearth/xml/node.rb +2 -2
- data/lib/hearth.rb +32 -5
- data/sig/lib/hearth/aliases.rbs +4 -0
- data/sig/lib/hearth/api_error.rbs +13 -0
- data/sig/lib/hearth/auth_option.rbs +11 -0
- data/sig/lib/hearth/auth_schemes/anonymous.rbs +7 -0
- data/sig/lib/hearth/auth_schemes/http_api_key.rbs +7 -0
- data/sig/lib/hearth/auth_schemes/http_basic.rbs +7 -0
- data/sig/lib/hearth/auth_schemes/http_bearer.rbs +7 -0
- data/sig/lib/hearth/auth_schemes/http_digest.rbs +7 -0
- data/sig/lib/hearth/auth_schemes.rbs +13 -0
- data/sig/lib/hearth/block_io.rbs +9 -0
- data/sig/lib/hearth/client_stubs.rbs +5 -0
- data/sig/lib/hearth/configuration.rbs +7 -0
- data/sig/lib/hearth/dns/host_address.rbs +13 -0
- data/sig/lib/hearth/dns/host_resolver.rbs +19 -0
- data/sig/lib/hearth/http/api_error.rbs +13 -0
- data/sig/lib/hearth/http/client.rbs +9 -0
- data/sig/lib/hearth/http/field.rbs +19 -0
- data/sig/lib/hearth/http/fields.rbs +43 -0
- data/sig/lib/hearth/http/request.rbs +25 -0
- data/sig/lib/hearth/http/response.rbs +21 -0
- data/sig/lib/hearth/identities/anonymous.rbs +6 -0
- data/sig/lib/hearth/identities/http_api_key.rbs +9 -0
- data/sig/lib/hearth/identities/http_bearer.rbs +9 -0
- data/sig/lib/hearth/identities/http_login.rbs +11 -0
- data/sig/lib/hearth/identities.rbs +9 -0
- data/sig/lib/hearth/identity_resolver.rbs +7 -0
- data/sig/lib/hearth/interceptor.rbs +9 -0
- data/sig/lib/hearth/interceptor_context.rbs +15 -0
- data/sig/lib/hearth/interceptor_list.rbs +16 -0
- data/sig/lib/hearth/interfaces.rbs +65 -0
- data/sig/lib/hearth/output.rbs +11 -0
- data/sig/lib/hearth/plugin_list.rbs +15 -0
- data/sig/lib/hearth/query/param.rbs +17 -0
- data/sig/lib/hearth/query/param_list.rbs +25 -0
- data/sig/lib/hearth/request.rbs +9 -0
- data/sig/lib/hearth/response.rbs +11 -0
- data/sig/lib/hearth/retry/adaptive.rbs +13 -0
- data/sig/lib/hearth/retry/exponential_backoff.rbs +7 -0
- data/sig/lib/hearth/retry/standard.rbs +13 -0
- data/sig/lib/hearth/retry/strategy.rbs +11 -0
- data/sig/lib/hearth/retry.rbs +9 -0
- data/sig/lib/hearth/signers/anonymous.rbs +9 -0
- data/sig/lib/hearth/signers/http_api_key.rbs +9 -0
- data/sig/lib/hearth/signers/http_basic.rbs +9 -0
- data/sig/lib/hearth/signers/http_bearer.rbs +9 -0
- data/sig/lib/hearth/signers/http_digest.rbs +9 -0
- data/sig/lib/hearth/signers.rbs +9 -0
- data/sig/lib/hearth/structure.rbs +7 -0
- data/sig/lib/hearth/union.rbs +5 -0
- data/sig/lib/hearth/waiters/waiter.rbs +17 -0
- metadata +132 -22
- data/lib/hearth/http/headers.rb +0 -70
- data/lib/hearth/middleware/around_handler.rb +0 -24
- data/lib/hearth/middleware/request_handler.rb +0 -24
- data/lib/hearth/middleware/response_handler.rb +0 -25
- data/lib/hearth/middleware_builder.rb +0 -246
- data/lib/hearth/stubbing/client_stubs.rb +0 -115
- data/lib/hearth/stubbing/stubs.rb +0 -32
- data/lib/hearth/waiters/errors.rb +0 -15
- data/sig/lib/seahorse/api_error.rbs +0 -10
- data/sig/lib/seahorse/document.rbs +0 -2
- data/sig/lib/seahorse/http/api_error.rbs +0 -21
- data/sig/lib/seahorse/http/headers.rbs +0 -47
- data/sig/lib/seahorse/http/response.rbs +0 -21
- data/sig/lib/seahorse/simple_delegator.rbs +0 -3
- data/sig/lib/seahorse/structure.rbs +0 -18
- data/sig/lib/seahorse/stubbing/client_stubs.rbs +0 -103
- data/sig/lib/seahorse/stubbing/stubs.rbs +0 -14
- data/sig/lib/seahorse/union.rbs +0 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bace852980aa4785929fce82aeb1a0b683fd6cf1f77d83d1dee39315d8177361
|
|
4
|
+
data.tar.gz: bff4b301d6940ccb485973b728b761e0d773489068cb093bf1789fcfe8cd1c35
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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.
|
|
4
|
+
1.0.0.pre2 (2023-12-19)
|
|
5
5
|
------------------
|
|
6
6
|
|
|
7
|
-
* Feature -
|
|
7
|
+
* Feature - Second initial public pre-release for Smithy Ruby SDKs.
|
|
8
8
|
|
|
9
|
-
0.
|
|
9
|
+
1.0.0.pre1 (2022-01-10)
|
|
10
10
|
------------------
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
* Feature - Initial public pre-release for Smithy Ruby SDKs.
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.0.0.
|
|
1
|
+
1.0.0.pre2
|
data/lib/hearth/api_error.rb
CHANGED
|
@@ -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
|
data/lib/hearth/context.rb
CHANGED
|
@@ -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
|
-
@
|
|
16
|
+
@interceptors = options[:interceptors] || InterceptorList.new
|
|
13
17
|
@metadata = options[:metadata] || {}
|
|
14
18
|
end
|
|
15
19
|
|
|
16
|
-
# @return [
|
|
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 [
|
|
29
|
-
attr_reader :
|
|
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
|