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
data/lib/hearth/http.rb CHANGED
@@ -3,9 +3,13 @@
3
3
  require 'cgi'
4
4
  require_relative 'http/api_error'
5
5
  require_relative 'http/client'
6
+ require_relative 'http/error_inspector'
6
7
  require_relative 'http/error_parser'
7
- require_relative 'http/headers'
8
- require_relative 'http/middleware/content_length'
8
+ require_relative 'http/field'
9
+ require_relative 'http/fields'
10
+ require_relative 'http/header_list_builder'
11
+ require_relative 'http/header_list_parser'
12
+ require_relative 'http/middleware'
9
13
  require_relative 'http/networking_error'
10
14
  require_relative 'http/request'
11
15
  require_relative 'http/response'
@@ -13,21 +17,28 @@ require_relative 'http/response'
13
17
  module Hearth
14
18
  # HTTP namespace for HTTP specific functionality. Also includes utility
15
19
  # methods for URI escaping.
16
- # @api private
17
20
  module HTTP
18
- # TODO: - do these belong here?
19
21
  class << self
20
22
  # URI escapes the given value.
21
23
  #
22
- # Hearth::_escape("a b/c")
24
+ # Hearth.uri_escape("a b/c")
23
25
  # #=> "a%20b%2Fc"
24
26
  #
25
27
  # @param [String] value
26
28
  # @return [String] URI encoded value except for '+' and '~'.
29
+ # @api private
27
30
  def uri_escape(value)
28
31
  CGI.escape(value.encode('UTF-8')).gsub('+', '%20').gsub('%7E', '~')
29
32
  end
30
33
 
34
+ # URI escapes the given path.
35
+ #
36
+ # Hearth.uri_escape_path("a b/c")
37
+ # #=> "a%20b/c"
38
+ #
39
+ # @param [String] path
40
+ # @return [String] URI encoded path except for '+' and '~'.
41
+ # @api private
31
42
  def uri_escape_path(path)
32
43
  path.gsub(%r{[^/]+}) { |part| uri_escape(part) }
33
44
  end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hearth
4
+ module Identities
5
+ # Anonymous identity.
6
+ class Anonymous < Identities::Base; end
7
+ end
8
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hearth
4
+ module Identities
5
+ # Identity class for API Key authentication.
6
+ class HTTPApiKey < Identities::Base
7
+ def initialize(key:, **kwargs)
8
+ super(**kwargs)
9
+ @key = key
10
+ end
11
+
12
+ # @return [String]
13
+ attr_reader :key
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hearth
4
+ module Identities
5
+ # Identity class for bearer token authentication.
6
+ class HTTPBearer < Identities::Base
7
+ def initialize(token:, **kwargs)
8
+ super(**kwargs)
9
+ @token = token
10
+ end
11
+
12
+ # @return [String]
13
+ attr_reader :token
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hearth
4
+ module Identities
5
+ # Identity class for login authentication.
6
+ class HTTPLogin < Identities::Base
7
+ def initialize(username:, password:, **kwargs)
8
+ super(**kwargs)
9
+ @username = username
10
+ @password = password
11
+ end
12
+
13
+ # @return [String]
14
+ attr_reader :username
15
+
16
+ # @return [String]
17
+ attr_reader :password
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hearth
4
+ # Namespace for all Identity classes.
5
+ module Identities
6
+ # Base class for all Identity classes.
7
+ class Base
8
+ def initialize(expiration: nil)
9
+ @expiration = expiration
10
+ end
11
+
12
+ # @return [Time, nil]
13
+ attr_reader :expiration
14
+ end
15
+ end
16
+ end
17
+
18
+ require_relative 'identities/anonymous'
19
+ require_relative 'identities/http_api_key'
20
+ require_relative 'identities/http_bearer'
21
+ require_relative 'identities/http_login'
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hearth
4
+ # Basic Identity resolver that uses a proc to resolve an Identity.
5
+ class IdentityProvider
6
+ # @param [Proc] proc A proc that takes identity properties (Hash)
7
+ # and returns a {Hearth::Identities::Base}.
8
+ def initialize(proc)
9
+ @proc = proc
10
+ end
11
+
12
+ # @param [Hash] properties
13
+ def identity(properties = {})
14
+ @proc.call(properties)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,506 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hearth
4
+ # # Interceptors
5
+ # Interceptors are a generic extension point that allows injecting
6
+ # logic at specific stages of execution within the SDK. Logic injection
7
+ # is done with hooks that the interceptor implements.
8
+ #
9
+ # Hooks are either read-only or read/write.
10
+ # Read-only hooks allow an interceptor to read the input,
11
+ # transport request, transport response or output messages.
12
+ # Read/write hooks allow an interceptor to modify one of these messages.
13
+ #
14
+ # # Creating an Interceptor
15
+ # To create an Interceptor, you must provide a hash with each key being
16
+ # a hook name and each value being a callable with arity 1 (context).
17
+ # For example:
18
+ #
19
+ # callbacks = {
20
+ # read_before_execution: proc { |context| puts "Before execution" },
21
+ # read_after_execution: proc { |context| puts "After execution" }
22
+ # }
23
+ # interceptor = Interceptor.new(callbacks)
24
+ #
25
+ # More advanced interceptors can be created by implementing the hooks
26
+ # directly in a class. For example:
27
+ #
28
+ # class MyInterceptor
29
+ # def initialize
30
+ # # keep state or do other initialization
31
+ # end
32
+ #
33
+ # def read_before_execution(context)
34
+ # puts "Before execution"
35
+ # end
36
+ #
37
+ # def read_after_execution(context)
38
+ # puts "After execution"
39
+ # end
40
+ # end
41
+ #
42
+ # # Registering an Interceptor
43
+ # Interceptors are registered by appending them to an {InterceptorList}
44
+ # and passing it to the the Client's Config. For example:
45
+ #
46
+ # interceptors = InterceptorList.new([MyInterceptor.new])
47
+ # config = Organization::Config.new(interceptors: interceptors)
48
+ # client = Organization::Client.new(config: config)
49
+ # client.operation
50
+ # #=> "Before execution"
51
+ # #=> "After execution"
52
+ #
53
+ # # Available Hooks
54
+ # The available hooks can be retrieved by calling {Interceptor.hooks}.
55
+ #
56
+ # The following hooks are available:
57
+ # * :read_before_execution
58
+ # * :modify_before_serialization
59
+ # * :read_before_serialization
60
+ # * :read_after_serialization
61
+ # * :modify_before_retry_loop
62
+ # * :read_before_attempt
63
+ # * :modify_before_signing
64
+ # * :read_before_signing
65
+ # * :read_after_signing
66
+ # * :modify_before_transmit
67
+ # * :read_before_transmit
68
+ # * :read_after_transmit
69
+ # * :modify_before_deserialization
70
+ # * :read_before_deserialization
71
+ # * :read_after_deserialization
72
+ # * :modify_before_attempt_completion
73
+ # * :read_after_attempt
74
+ # * :modify_before_completion
75
+ # * :read_after_execution
76
+ #
77
+ # # Hook Details
78
+ # The following sections describe each hook in detail.
79
+ #
80
+ # ## :read_before_execution
81
+ # A hook called at the start of an execution, before the SDK
82
+ # does anything else.
83
+ #
84
+ # When: This will ALWAYS be called once per execution. The duration
85
+ # between invocation of this hook and :read_after_execution is very
86
+ # close to full duration of the execution.
87
+ #
88
+ # Available Information: The {InterceptorContext#input} is ALWAYS
89
+ # available. Other information WILL NOT be available.
90
+ #
91
+ # Error Behavior: Errors raised by this hook will be stored
92
+ # until all interceptors have had their :read_before_execution
93
+ # invoked. Other hooks will then be skipped and execution will jump to
94
+ # :modify_before_completion with the raised error as the
95
+ # {Output#error} in {InterceptorContext#output}. If multiple
96
+ # :read_before_execution methods raise errors, the latest
97
+ # will be used and earlier ones will be logged and dropped.
98
+ #
99
+ # ## :modify_before_serialization
100
+ # A hook called before the input message is marshalled into a
101
+ # transport message. This method has the ability to modify the
102
+ # input message.
103
+ #
104
+ # When: This will ALWAYS be called once per execution, except when a
105
+ # failure occurs earlier in the request pipeline.
106
+ #
107
+ # Available Information: The {InterceptorContext#input} is ALWAYS
108
+ # available. This input may have been modified by earlier
109
+ # :modify_before_serialization hooks, and may be modified further by
110
+ # later hooks. Other information WILL NOT be available.
111
+ #
112
+ # Error Behavior: If errors are raised by this hook, execution will
113
+ # jump to :modify_before_completion with the raised error as the
114
+ # {Output#error} in {InterceptorContext#output}.
115
+ #
116
+ # ## :read_before_serialization
117
+ # A hook called before the input message is marshalled into a transport
118
+ # message.
119
+ #
120
+ # When: This will ALWAYS be called once per execution, except when a
121
+ # failure occurs earlier in the request pipeline. The duration
122
+ # between invocation of this hook and :read_after_serialization is
123
+ # very close to the amount of time spent marshalling the request.
124
+ #
125
+ # Available Information: The {InterceptorContext#input} is
126
+ # ALWAYS available. Other information WILL NOT be available.
127
+ #
128
+ # Error Behavior: If errors are raised by this hook, execution will
129
+ # jump to :modify_before_completion with the raised error as the
130
+ # {Output#error} in {InterceptorContext#output}.
131
+ #
132
+ # ## :read_after_serialization
133
+ # A hook called after the input message is marshalled into a transport
134
+ # message.
135
+ #
136
+ # When: This will ALWAYS be called once per execution, except when a
137
+ # failure occurs earlier in the request pipeline. The duration
138
+ # between invocation of this hook and :read_before_serialization is
139
+ # very close to the amount of time spent marshalling the request.
140
+ #
141
+ # Available Information: The {InterceptorContext#input},
142
+ # {InterceptorContext#request} are ALWAYS available. Other
143
+ # information WILL NOT be available.
144
+ #
145
+ # Error Behavior: If errors are raised by this hook, execution will
146
+ # jump to :modify_before_completion with the raised error as the
147
+ # {Output#error} in {InterceptorContext#output}.
148
+ #
149
+ # ## :modify_before_retry_loop
150
+ # A hook called before the retry loop is entered. This method
151
+ # has the ability to modify the transport request message.
152
+ #
153
+ # When: This will ALWAYS be called once per execution, except when a
154
+ # failure occurs earlier in the request pipeline.
155
+ #
156
+ # Available Information: The {InterceptorContext#input} and
157
+ # {InterceptorContext#request} are ALWAYS available. Other
158
+ # information WILL NOT be available.
159
+ #
160
+ # Error Behavior: If errors are raised by this hook, execution will
161
+ # jump to :modify_before_completion with the raised error as the
162
+ # {Output#error} in {InterceptorContext#output}.
163
+ #
164
+ # ## :read_before_attempt
165
+ # A hook called before each attempt at sending the transmission
166
+ # request message to the service.
167
+ #
168
+ # When: This will ALWAYS be called once per attempt, except when a
169
+ # failure occurs earlier in the request pipeline. This method will be
170
+ # called multiple times in the event of retries.
171
+ #
172
+ # Available Information: The {InterceptorContext#input} and
173
+ # {InterceptorContext#request} are ALWAYS available. Other
174
+ # information WILL NOT be available. In the event of retries, the
175
+ # {InterceptorContext} WILL include changes made in previous
176
+ # attempts (e.g. by other interceptors).
177
+ #
178
+ # Error Behavior: Errors raised by this hook will be stored
179
+ # until all interceptors have had their :read_before_attempt
180
+ # invoked. Other hooks will then be skipped and execution will jump to
181
+ # :modify_before_attempt_completion with the raised error as the
182
+ # {Output#error} in {InterceptorContext#output}. If multiple
183
+ # :read_before_attempt methods raise errors, the latest will be used
184
+ # and earlier ones will be logged and dropped.
185
+ #
186
+ # ## :modify_before_signing
187
+ # A hook called before the transport request message is signed. This
188
+ # method has the ability to modify the transport request message.
189
+ #
190
+ # When: This will ALWAYS be called once per attempt, except when a
191
+ # failure occurs earlier in the request pipeline. This method may be
192
+ # called multiple times in the event of retries.
193
+ #
194
+ # Available Information: The {InterceptorContext#input} and
195
+ # {InterceptorContext#request} are ALWAYS available. The request may
196
+ # have been modified by earlier :modify_before_signing hooks, and may
197
+ # be modified further by later hooks. Other information WILL NOT be
198
+ # available. In the event of retries, the {InterceptorContext} WILL
199
+ # include changes made in previous attempts (e.g. by other middleware
200
+ # or interceptors).
201
+ #
202
+ # Error Behavior: If errors are raised by this hook, execution will
203
+ # jump to :modify_before_attempt_completion with the raised error as
204
+ # the {Output#error} in {InterceptorContext#output}.
205
+ #
206
+ # ## :read_before_signing
207
+ # A hook called before the transport request message is signed.
208
+ #
209
+ # When: This will ALWAYS be called once per attempt, except when a
210
+ # failure occurs earlier in the request pipeline. This method may be
211
+ # called multiple times in the event of retries. The duration between
212
+ # invocation of this hook and :read_after_signing is very close to
213
+ # the amount of time spent signing the request.
214
+ #
215
+ # Available Information: The {InterceptorContext#input} and
216
+ # {InterceptorContext#request} are ALWAYS available. Other
217
+ # information WILL NOT be available. In the event of retries, the
218
+ # {InterceptorContext} WILL include changes made in previous
219
+ # attempts (e.g. by other interceptors).
220
+ #
221
+ # Error Behavior: If errors are raised by this hook, execution will
222
+ # jump to :modify_before_attempt_completion with the raised error as
223
+ # the {Output#error} in {InterceptorContext#output}.
224
+ #
225
+ # ## :read_after_signing
226
+ # A hook called after the transport request message is signed.
227
+ #
228
+ # When: This will ALWAYS be called once per attempt, except when a
229
+ # failure occurs earlier in the request pipeline. This method may be
230
+ # called multiple times in the event of retries. The duration between
231
+ # invocation of this hook and :read_before_signing is very close to
232
+ # the amount of time spent signing the request.
233
+ #
234
+ # Available Information: The {InterceptorContext#input} and
235
+ # {InterceptorContext#request} are ALWAYS available. Other
236
+ # information WILL NOT be available. In the event of retries, the
237
+ # {InterceptorContext} WILL include changes made in previous
238
+ # attempts (e.g. by other interceptors).
239
+ #
240
+ # Error Behavior: If errors are raised by this hook, execution will
241
+ # jump to :modify_before_attempt_completion with the raised error as
242
+ # the {Output#error} in {InterceptorContext#output}.
243
+ #
244
+ # ## :modify_before_transmit
245
+ # A hook called before the transport request message is sent to the
246
+ # service. This method has the ability to modify the transport request
247
+ # message.
248
+ #
249
+ # When: This will ALWAYS be called once per attempt, except when a
250
+ # failure occurs earlier in the request pipeline. This method may be
251
+ # called multiple times in the event of retries.
252
+ #
253
+ # Available Information: The {InterceptorContext#input} and
254
+ # {InterceptorContext#request} are ALWAYS available. The request may
255
+ # have been modified by earlier :modify_before_transmit hooks, and
256
+ # may be modified further by later hooks. Other information WILL NOT be
257
+ # available. In the event of retries, the {InterceptorContext} WILL
258
+ # include changes made in previous attempts (e.g. by other interceptors).
259
+ #
260
+ # Error Behavior: If errors are raised by this hook, execution will
261
+ # jump to :modify_before_attempt_completion with the raised error as
262
+ # the {Output#error} in {InterceptorContext#output}.
263
+ #
264
+ # ## :read_before_transmit
265
+ # A hook called before the transport request message is sent to the
266
+ # service.
267
+ #
268
+ # When: This will ALWAYS be called once per attempt, except when a
269
+ # failure occurs earlier in the request pipeline. This method may be
270
+ # called multiple times in the event of retries. The duration between
271
+ # invocation of this hook and :read_after_transmit is very close to
272
+ # the amount of time spent communicating with the service. Depending on
273
+ # the protocol, the duration may not include the time spent reading the
274
+ # response data.
275
+ #
276
+ # Available Information: The {InterceptorContext#input} and
277
+ # {InterceptorContext#request} are ALWAYS available. Other
278
+ # information WILL NOT be available. In the event of retries, the
279
+ # {InterceptorContext} WILL include changes made in previous
280
+ # attempts (e.g. by other interceptors).
281
+ #
282
+ # Error Behavior: If errors are raised by this hook, execution will
283
+ # jump to :modify_before_attempt_completion with the raised error as
284
+ # the {Output#error} in {InterceptorContext#output}.
285
+ #
286
+ # ## :read_after_transmit
287
+ # A hook called after the transport response message is sent to the
288
+ # service and a transport response message is received.
289
+ #
290
+ # When: This will ALWAYS be called once per attempt, except when a
291
+ # failure occurs earlier in the request pipeline. This method may be
292
+ # called multiple times in the event of retries. The duration between
293
+ # invocation of this hook and :read_before_transmit is very close to
294
+ # the amount of time spent communicating with the service. Depending on
295
+ # the protocol, the duration may not include the time spent reading the
296
+ # response data.
297
+ #
298
+ # Available Information: The {InterceptorContext#input},
299
+ # {InterceptorContext#request}, and {InterceptorContext#response}
300
+ # are ALWAYS available. Other information WILL NOT be available. In the
301
+ # event of retries, the {InterceptorContext} WILL include changes
302
+ # made in previous attempts (e.g. by other interceptors).
303
+ #
304
+ # Error Behavior: If errors are raised by this hook, execution will
305
+ # jump to :modify_before_attempt_completion with the raised error as
306
+ # the {Output#error} in {InterceptorContext#output}.
307
+ #
308
+ # ## :modify_before_deserialization
309
+ # A hook called before the transport response message is unmarshalled.
310
+ # This method has the ability to modify the transport response message.
311
+ #
312
+ # When: This will ALWAYS be called once per attempt, except when a
313
+ # failure occurs earlier in the request pipeline. This method may be
314
+ # called multiple times in the event of retries.
315
+ #
316
+ # Available Information: The {InterceptorContext#input},
317
+ # {InterceptorContext#request}, and {InterceptorContext#response}
318
+ # are ALWAYS available. The response may have been modified by earlier
319
+ # :modify_before_deserialization hooks, and may be modified further by
320
+ # later hooks. Other information WILL NOT be available. In the event of
321
+ # retries, the {InterceptorContext} WILL include changes made in
322
+ # previous attempts (e.g. by other interceptors).
323
+ #
324
+ # Error Behavior: If errors are raised by this hook, execution will
325
+ # jump to :modify_before_attempt_completion with the raised error as
326
+ # the {Output#error} in {InterceptorContext#output}.
327
+ #
328
+ # ## :read_before_deserialization
329
+ # A hook called before the transport response message is unmarshalled.
330
+ #
331
+ # When: This will ALWAYS be called once per attempt, except when a
332
+ # failure occurs earlier in the request pipeline. This method may be
333
+ # called multiple times in the event of retries. The duration between
334
+ # invocation of this hook and :read_after_deserialization is very
335
+ # close to the amount of time spent unmarshalling the service response.
336
+ # Depending on the protocol and operation, the duration may include the
337
+ # time spent downloading the response data.
338
+ #
339
+ # Available Information: The {InterceptorContext#input},
340
+ # {InterceptorContext#request}, and {InterceptorContext#response}
341
+ # are ALWAYS available. Other information WILL NOT be available. In the
342
+ # event of retries, the {InterceptorContext} WILL include changes
343
+ # made in previous attempts (e.g. by other interceptors).
344
+ #
345
+ # Error Behavior: If errors are raised by this hook, execution will
346
+ # jump to :modify_before_attempt_completion with the raised error as
347
+ # the {Output#error} in {InterceptorContext#output}.
348
+ #
349
+ # ## :read_after_deserialization
350
+ # A hook called after the transport response message is unmarshalled.
351
+ #
352
+ # When: This will ALWAYS be called once per attempt, except when a
353
+ # failure occurs earlier in the request pipeline. The duration between
354
+ # invocation of this hook and :read_before_deserialization is very
355
+ # close to the amount of time spent unmarshalling the service response.
356
+ # Depending on the protocol and operation, the duration may include the
357
+ # time spent downloading the response data.
358
+ #
359
+ # Available Information: The {InterceptorContext#input},
360
+ # {InterceptorContext#request}, {InterceptorContext#response}
361
+ # and {InterceptorContext#output} are ALWAYS available. In the event
362
+ # of retries, the {InterceptorContext} WILL include changes made
363
+ # in previous attempts (e.g. by other interceptors).
364
+ #
365
+ # Error Behavior: If errors are raised by this hook, execution will
366
+ # jump to :modify_before_attempt_completion with the raised error as
367
+ # the {Output#error} in {InterceptorContext#output}.
368
+ #
369
+ # ## :modify_before_attempt_completion
370
+ # A hook called when an attempt is completed. This method has the
371
+ # ability to modify the output message or error matching
372
+ # the currently-executing operation.
373
+ #
374
+ # When: This will ALWAYS be called once per attempt, except when a
375
+ # failure occurs before :read_before_attempt. This method may
376
+ # be called multiple times in the event of retries.
377
+ #
378
+ # Available Information: The {InterceptorContext#input},
379
+ # {InterceptorContext#request}, {InterceptorContext#response} and
380
+ # {InterceptorContext#output} are ALWAYS available. In the event
381
+ # of retries, the {InterceptorContext} WILL include changes made
382
+ # in previous attempts (e.g. by other interceptors).
383
+ #
384
+ # Error Behavior: If errors are raised by this hook, execution will
385
+ # jump to :read_after_attempt with the raised error as the
386
+ # {Output#error} in {InterceptorContext#output}.
387
+ #
388
+ # ## :read_after_attempt
389
+ # A hook called when an attempt is completed.
390
+ #
391
+ # When: This will ALWAYS be called once per attempt, as long as
392
+ # :read_before_attempt has been executed.
393
+ #
394
+ # Available Information: The {InterceptorContext#input},
395
+ # {InterceptorContext#request}, {InterceptorContext#response} and
396
+ # {InterceptorContext#output} are ALWAYS available. The
397
+ # {InterceptorContext#response} is available if a response
398
+ # was received by the service for this attempt. In the event of retries,
399
+ # the {InterceptorContext} WILL include changes made in previous
400
+ # attempts (e.g. by other interceptors).
401
+ #
402
+ # Error Behavior: Errors raised by this hook will be stored
403
+ # until all interceptors have had their :read_after_attempt invoked.
404
+ # If multiple :read_after_attempt methods raise errors, the latest
405
+ # will be used and earlier ones will be logged and dropped. If the retry
406
+ # strategy determines that {Output#error} is a retryable error, execution
407
+ # will then jump to :read_before_attempt. Otherwise, execution will jump
408
+ # to :modify_before_completion.
409
+ #
410
+ # ## :modify_before_completion
411
+ # A hook called when an execution is completed. This method has the
412
+ # ability to modify the output message or error matching
413
+ # the currently-executing operation.
414
+ #
415
+ # When: This will ALWAYS be called once per execution.
416
+ #
417
+ # Available Information: The {InterceptorContext#input} and
418
+ # {InterceptorContext#output} are ALWAYS available. The
419
+ # {InterceptorContext#request} and {InterceptorContext#response}
420
+ # are available if the execution proceeded far enough for them to be
421
+ # generated.
422
+ #
423
+ # Error Behavior: If errors are raised by this hook, execution will
424
+ # jump to :read_after_execution with the raised error as the
425
+ # {Output#error} in {InterceptorContext#output}.
426
+ #
427
+ # ## :read_after_execution
428
+ # A hook called when an execution is completed.
429
+ #
430
+ # When: This will ALWAYS be called once per execution. The duration
431
+ # between invocation of this hook and :read_before_execution is very
432
+ # close to the full duration of the execution.
433
+ #
434
+ # Available Information: The {InterceptorContext#input} and
435
+ # {InterceptorContext#output} are ALWAYS available. The
436
+ # {InterceptorContext#request} and {InterceptorContext#response}
437
+ # are available if the execution proceeded far enough for them to be
438
+ # generated.
439
+ #
440
+ # Error Behavior: Errors raised by this hook will be stored until all
441
+ # interceptors have had their :read_after_execution invoked. The
442
+ # error will then be treated as the {Output#error} raised by the
443
+ # operation. If multiple :read_after_execution methods raise
444
+ # errors, the latest will be used and earlier ones will be logged and
445
+ # dropped.
446
+ #
447
+ class Interceptor
448
+ # @api private
449
+ @hooks = [
450
+ READ_BEFORE_EXECUTION = :read_before_execution,
451
+ MODIFY_BEFORE_SERIALIZATION = :modify_before_serialization,
452
+ READ_BEFORE_SERIALIZATION = :read_before_serialization,
453
+ READ_AFTER_SERIALIZATION = :read_after_serialization,
454
+ MODIFY_BEFORE_RETRY_LOOP = :modify_before_retry_loop,
455
+ READ_BEFORE_ATTEMPT = :read_before_attempt,
456
+ MODIFY_BEFORE_SIGNING = :modify_before_signing,
457
+ READ_BEFORE_SIGNING = :read_before_signing,
458
+ READ_AFTER_SIGNING = :read_after_signing,
459
+ MODIFY_BEFORE_TRANSMIT = :modify_before_transmit,
460
+ READ_BEFORE_TRANSMIT = :read_before_transmit,
461
+ READ_AFTER_TRANSMIT = :read_after_transmit,
462
+ MODIFY_BEFORE_DESERIALIZATION = :modify_before_deserialization,
463
+ READ_BEFORE_DESERIALIZATION = :read_before_deserialization,
464
+ READ_AFTER_DESERIALIZATION = :read_after_deserialization,
465
+ MODIFY_BEFORE_ATTEMPT_COMPLETION = :modify_before_attempt_completion,
466
+ READ_AFTER_ATTEMPT = :read_after_attempt,
467
+ MODIFY_BEFORE_COMPLETION = :modify_before_completion,
468
+ READ_AFTER_EXECUTION = :read_after_execution
469
+ ]
470
+
471
+ # Creates a new Interceptor.
472
+ #
473
+ # @param [Hash<Symbol, Proc>] callbacks
474
+ # A hash of hook names to callbacks. The callbacks will be invoked
475
+ # when the hook is called. The callback will be passed the
476
+ # {InterceptorContext} for the current execution.
477
+ def initialize(callbacks = {})
478
+ @callbacks = {}
479
+
480
+ Interceptor.hooks.each do |hook|
481
+ next unless callbacks[hook]
482
+
483
+ unless valid_callback?(callbacks[hook])
484
+ raise ArgumentError,
485
+ "#{hook} must be a callable with arity 1 (context)"
486
+ end
487
+
488
+ @callbacks[hook] = callbacks[hook]
489
+ define_singleton_method(hook) do |context|
490
+ @callbacks[hook].call(context)
491
+ end
492
+ end
493
+ end
494
+
495
+ class << self
496
+ # @return [Array<Symbol>] Returns a list of all available hooks.
497
+ attr_reader :hooks
498
+ end
499
+
500
+ private
501
+
502
+ def valid_callback?(callback)
503
+ callback.respond_to?(:call) && callback.arity == 1
504
+ end
505
+ end
506
+ end