springcm-sdk 0.3.6 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2bcbec6f89c659710286d4dac5b6e6197272ca2b90a20202807d68a953bfd4ee
4
- data.tar.gz: c8e2f2e943de9719f61d47dec3a5f3c247cbb99ce4b33e852da986a4acd595e2
3
+ metadata.gz: 4ede0e8cbe39a1ba56490a8747d394136877c4ba297f42bc618d665a37822b5b
4
+ data.tar.gz: 2c6c5bf9194b9f63f937f491cd3522d8175db3d8aabd5cf799b8a09aba7689e6
5
5
  SHA512:
6
- metadata.gz: be09de4cbef4485fd4ae2749f158f12cb23f5bfbdb7377a81fe989f793fab61c4dadd6948241646adf8a6bcd8870c2da300a361208115477e791396ffb4ba10e
7
- data.tar.gz: 336f3fd0bf01bd1b6a89db940a76260aca9a25b5fdc2561de1516336832b7124c9ff8e946770eda7331d727746d84af1a243c72de9920dad0350021feb796a1e
6
+ metadata.gz: 9aee61e667d073e51bc57f7e8aa00c67e6f47067cc106b11e1caee6306836e390035df29d63714f7f10c8d6351bbca8eaabca34ef95a65a4cc71eecbd60f9874
7
+ data.tar.gz: 40aeda6cd074142c6546a3451fd29c495dc1f1a73bebce8dab2d2382f730e268cc5690de41d9c89b7b5203d149a5915a7997802e871b7bc559c3e70558271512
data/CHANGELOG.md CHANGED
@@ -4,6 +4,16 @@ All notable changes to springcm-sdk will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.4.0] - 2019-12-27
8
+ ### Added
9
+ * Faraday middleware for authorization expiration and rate limit handling.
10
+ * Faraday middleware for retrying on Faraday::ConnectionFailed. Can be
11
+ disabled via new Client options.
12
+
13
+ ### Changed
14
+ * Adjust auth window to re-authenticate no more than 5 minutes before
15
+ access token expiration.
16
+
7
17
  ## [0.3.6] - 2019-12-23
8
18
  ### Changed
9
19
  * Fix resource list behavior for history items. Was returning the document's
@@ -79,7 +89,7 @@ All notable changes to springcm-sdk will be documented in this file.
79
89
  ### Added
80
90
  * Initial release to reserve gem name
81
91
 
82
- [Unreleased]: https://github.com/paulholden2/springcm-sdk/compare/0.3.6...HEAD
92
+ [Unreleased]: https://github.com/paulholden2/springcm-sdk/compare/0.4.0...HEAD
83
93
  [0.1.0]: https://github.com/paulholden2/springcm-sdk/releases/tag/0.1.0
84
94
  [0.1.1]: https://github.com/paulholden2/springcm-sdk/releases/tag/0.1.1
85
95
  [0.1.2]: https://github.com/paulholden2/springcm-sdk/releases/tag/0.1.2
@@ -91,3 +101,4 @@ All notable changes to springcm-sdk will be documented in this file.
91
101
  [0.3.4]: https://github.com/paulholden2/springcm-sdk/releases/tag/0.3.4
92
102
  [0.3.5]: https://github.com/paulholden2/springcm-sdk/releases/tag/0.3.5
93
103
  [0.3.6]: https://github.com/paulholden2/springcm-sdk/releases/tag/0.3.6
104
+ [0.4.0]: https://github.com/paulholden2/springcm-sdk/releases/tag/0.4.0
data/bin/console CHANGED
File without changes
data/exe/springcm CHANGED
File without changes
@@ -3,19 +3,31 @@ require "json"
3
3
  require "springcm-sdk/account"
4
4
  require "springcm-sdk/folder"
5
5
  require "springcm-sdk/document"
6
+ require "springcm-sdk/middleware"
6
7
 
7
8
  module Springcm
8
9
  class Client
10
+ # Default API client options
11
+ DEFAULT_OPTIONS = {
12
+ # If true, the client will use a simple retry mechanism when connection
13
+ # to the API server fails due to e.g. temporary Internet service outage.
14
+ # The connection is re-attempted up to five times, delaying 2 ** n
15
+ # seconds between attempts, where n is the number of previous attempts.
16
+ retry_connection_failed: true
17
+ }.freeze
18
+
9
19
  attr_reader :access_token
10
20
 
11
21
  # @param data_center [String] Data center name, e.g. uatna11
12
22
  # @param client_id [String] Your API client ID
13
23
  # @param client_secret [String] Your API client secret
14
- def initialize(data_center, client_id, client_secret)
24
+ # @parma options [Hash] API client options
25
+ def initialize(data_center, client_id, client_secret, options=DEFAULT_OPTIONS)
15
26
  if !["na11", "uatna11", "eu11", "eu21", "na21", "us11"].include?(data_center)
16
27
  raise Springcm::ConnectionInfoError.new("Invalid data center '#{data_center.to_s}'")
17
28
  end
18
29
 
30
+ @options = options
19
31
  @data_center = data_center
20
32
  @client_id = client_id
21
33
  @client_secret = client_secret
@@ -28,7 +40,12 @@ module Springcm
28
40
  # @param safe If truthy, connection failure does not raise an exception
29
41
  # @return [Boolean] Whether connection was successful
30
42
  def connect(safe=true)
31
- conn = Faraday.new(url: auth_url)
43
+ conn = Faraday.new(url: auth_url) do |conn|
44
+ conn.request :retry, retry_statuses: [429], exceptions: [Springcm::RateLimitExceededError]
45
+ conn.use Springcm::Middleware::RateLimit
46
+ conn.use Springcm::Middleware::RetryConnectionFailed if @options[:retry_connection_failed]
47
+ conn.adapter :net_http
48
+ end
32
49
  res = conn.post do |req|
33
50
  req.headers['Content-Type'] = 'application/json'
34
51
  req.body = {
@@ -39,7 +56,7 @@ module Springcm
39
56
  if res.success?
40
57
  data = JSON.parse(res.body)
41
58
  @access_token = data.fetch("access_token")
42
- @expiry = Time.now + data.fetch("expires_in")
59
+ @expiry = Time.now + data.fetch("expires_in") - 300
43
60
  else
44
61
  @access_token = nil
45
62
  @expiry = nil
@@ -169,15 +186,29 @@ module Springcm
169
186
  end
170
187
 
171
188
  def authorized_connection(*options)
189
+ if !authenticated?
190
+ connect!
191
+ end
192
+
172
193
  Faraday.new(*options) do |conn|
173
194
  options = [{
174
195
  max: 10,
175
196
  interval: 1,
176
197
  interval_randomness: 0.5,
177
198
  backoff_factor: 2,
178
- retry_statuses: [429]
199
+ retry_statuses: [401, 429],
200
+ exceptions: [Springcm::AuthExpiredError, Springcm::RateLimitExceededError],
201
+ retry_block: -> (env, options, retries, exception) {
202
+ if exception.class == Springcm::AuthExpiredError
203
+ connect!
204
+ env.request_headers['Authorization'] = "bearer #{@access_token}"
205
+ end
206
+ }
179
207
  }]
180
208
  conn.request :retry, *options
209
+ conn.use Springcm::Middleware::RateLimit
210
+ conn.use Springcm::Middleware::AuthExpire
211
+ conn.use Springcm::Middleware::RetryConnectionFailed if @options[:retry_connection_failed]
181
212
  conn.adapter :net_http
182
213
  conn.authorization('bearer', @access_token)
183
214
  end
@@ -0,0 +1,20 @@
1
+ module Springcm
2
+ module Middleware
3
+ class AuthExpire
4
+ attr_reader :options
5
+
6
+ def initialize(app, options={})
7
+ @app = app
8
+ @options = options
9
+ end
10
+
11
+ def call(env)
12
+ @app.call(env).on_complete do |response_env|
13
+ if response_env[:status] == 401
14
+ raise Springcm::AuthExpiredError.new
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,21 @@
1
+ module Springcm
2
+ module Middleware
3
+ class RateLimit
4
+ attr_reader :options
5
+
6
+ def initialize(app, options={})
7
+ @app = app
8
+ @options = options
9
+ end
10
+
11
+ def call(env)
12
+ @app.call(env).on_complete do |response_env|
13
+ body = JSON.parse(response_env[:body])
14
+ if body.fetch("Error", {}).fetch("ErrorCode", nil) == 103
15
+ raise Springcm::RateLimitExceededError.new
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,30 @@
1
+ module Springcm
2
+ module Middleware
3
+ class RetryConnectionFailed
4
+ attr_reader :options
5
+
6
+ def initialize(app, options={ retries: 5 })
7
+ @app = app
8
+ @options = options
9
+ end
10
+
11
+ def call(env)
12
+ retries = @options[:retries]
13
+ delay = 1
14
+ begin
15
+ @app.call(env).on_complete do |response_env|
16
+ end
17
+ rescue Faraday::ConnectionFailed => err
18
+ if retries > 0
19
+ retries -= 1
20
+ sleep delay
21
+ delay *= 2
22
+ retry
23
+ else
24
+ raise err
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,3 @@
1
+ require "springcm-sdk/middleware/rate_limit"
2
+ require "springcm-sdk/middleware/auth_expired"
3
+ require "springcm-sdk/middleware/retry_connection_failed"
@@ -1,3 +1,3 @@
1
1
  module Springcm
2
- VERSION = "0.3.6"
2
+ VERSION = "0.4.0"
3
3
  end
data/lib/springcm-sdk.rb CHANGED
@@ -20,4 +20,16 @@ module Springcm
20
20
  super("Invalid Client Id or Client Secret")
21
21
  end
22
22
  end
23
+
24
+ class AuthExpiredError < Error
25
+ def initialize
26
+ super("Authorization expired")
27
+ end
28
+ end
29
+
30
+ class RateLimitExceededError < Error
31
+ def initialize
32
+ super("Rate limit exceeded")
33
+ end
34
+ end
23
35
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: springcm-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.6
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Holden
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-12-24 00:00:00.000000000 Z
11
+ date: 2019-12-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -167,6 +167,10 @@ files:
167
167
  - lib/springcm-sdk/folder.rb
168
168
  - lib/springcm-sdk/helpers.rb
169
169
  - lib/springcm-sdk/history_item.rb
170
+ - lib/springcm-sdk/middleware.rb
171
+ - lib/springcm-sdk/middleware/auth_expired.rb
172
+ - lib/springcm-sdk/middleware/rate_limit.rb
173
+ - lib/springcm-sdk/middleware/retry_connection_failed.rb
170
174
  - lib/springcm-sdk/mixins/access_level.rb
171
175
  - lib/springcm-sdk/mixins/attributes.rb
172
176
  - lib/springcm-sdk/mixins/documents.rb
@@ -183,7 +187,7 @@ metadata:
183
187
  allowed_push_host: https://rubygems.org
184
188
  homepage_uri: https://github.com/paulholden2/springcm-sdk
185
189
  source_code_uri: https://github.com/paulholden2/springcm-sdk
186
- documentation_uri: https://rubydoc.info/github/paulholden2/springcm-sdk/0.3.6
190
+ documentation_uri: https://rubydoc.info/github/paulholden2/springcm-sdk/0.4.0
187
191
  changelog_uri: https://github.com/paulholden2/springcm-sdk/blob/master/CHANGELOG.md
188
192
  post_install_message:
189
193
  rdoc_options: []