wrapi 0.4.9 → 0.5.1
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 +9 -0
- data/Rakefile +0 -5
- data/lib/wrapi/api.rb +1 -1
- data/lib/wrapi/authentication.rb +4 -4
- data/lib/wrapi/configuration.rb +12 -4
- data/lib/wrapi/connection.rb +3 -2
- data/lib/wrapi/middleware/rate_throttle_middleware.rb +72 -0
- data/lib/wrapi/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e5de57aabdb5677515c6b65d9bbb49ad959aa4e27869603375df4768c2f6c2a4
|
|
4
|
+
data.tar.gz: e7dd3571378f5d4c9dc5005121e747e19acaa66d6090b64472eac38474d71a76
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 240a5ec0a2fe02c506d9079805fb7031c663d4fed78a0f93a703d00ba5102725764f166fbf9945fee68926b3f6875a28e339e338219e68b712683447aeef4dca
|
|
7
|
+
data.tar.gz: dfb2abce78abdc97ba8e5270e40bf27c68571b96b48655dc6f3d76f86f7ae067e17afa5b8b34462c09d9f1491ffc51bfe07e89f89c6148105d91f54b5a788937
|
data/CHANGELOG.md
CHANGED
|
@@ -68,3 +68,12 @@
|
|
|
68
68
|
## [0.4.9] - 2025-03-20
|
|
69
69
|
|
|
70
70
|
- freeze causes issue so connection options can't be merged!
|
|
71
|
+
|
|
72
|
+
## [0.5.0] - 2025-10-20
|
|
73
|
+
|
|
74
|
+
- generic use of token type
|
|
75
|
+
|
|
76
|
+
## [0.5.1] - 2025-11-10
|
|
77
|
+
|
|
78
|
+
- do not assign token type when empty
|
|
79
|
+
- add rate throttling depending parameters
|
data/Rakefile
CHANGED
|
@@ -6,15 +6,10 @@ require 'rake/testtask'
|
|
|
6
6
|
|
|
7
7
|
Dotenv.load
|
|
8
8
|
|
|
9
|
-
system './bin/cc-test-reporter before-build'
|
|
10
|
-
|
|
11
9
|
Rake::TestTask.new(:test) do |t|
|
|
12
10
|
t.libs << 'test'
|
|
13
11
|
t.libs << 'lib'
|
|
14
12
|
t.test_files = FileList['test/**/*_test.rb']
|
|
15
|
-
at_exit do
|
|
16
|
-
system './bin/cc-test-reporter after-build'
|
|
17
|
-
end
|
|
18
13
|
end
|
|
19
14
|
|
|
20
15
|
require 'rubocop/rake_task'
|
data/lib/wrapi/api.rb
CHANGED
|
@@ -23,7 +23,7 @@ module WrAPI
|
|
|
23
23
|
# @see WrAPI::Request
|
|
24
24
|
# @see WrAPI::Authentication
|
|
25
25
|
class API
|
|
26
|
-
attr_accessor
|
|
26
|
+
attr_accessor(*WrAPI::Configuration::VALID_OPTIONS_KEYS)
|
|
27
27
|
|
|
28
28
|
# Initializes a new API object with the given options.
|
|
29
29
|
#
|
data/lib/wrapi/authentication.rb
CHANGED
|
@@ -62,10 +62,10 @@ module WrAPI
|
|
|
62
62
|
def api_process_token(response)
|
|
63
63
|
raise ArgumentError.new("Response cannot be nil") if response.nil?
|
|
64
64
|
|
|
65
|
-
token = self.access_token = response['accessToken']
|
|
66
|
-
self.token_type = response['tokenType']
|
|
67
|
-
self.refresh_token = response['refreshToken']
|
|
68
|
-
self.token_expires = response['expiresIn']
|
|
65
|
+
token = self.access_token = response['accessToken'] if response['accessToken']
|
|
66
|
+
self.token_type = response['tokenType'] if response['tokenType']
|
|
67
|
+
self.refresh_token = response['refreshToken'] if response['refreshToken']
|
|
68
|
+
self.token_expires = response['expiresIn'] if response['expiresIn']
|
|
69
69
|
raise StandardError.new("Could not find valid accessToken; response #{response}") if token.to_s.empty?
|
|
70
70
|
|
|
71
71
|
token
|
data/lib/wrapi/configuration.rb
CHANGED
|
@@ -58,12 +58,18 @@ module WrAPI
|
|
|
58
58
|
:format,
|
|
59
59
|
:page_size,
|
|
60
60
|
:user_agent,
|
|
61
|
-
:pagination_class
|
|
61
|
+
:pagination_class,
|
|
62
|
+
:rate_limit,
|
|
63
|
+
:rate_period
|
|
62
64
|
].freeze
|
|
63
65
|
|
|
64
66
|
# By default, don't set any connection options
|
|
65
67
|
DEFAULT_CONNECTION_OPTIONS = {}
|
|
66
68
|
|
|
69
|
+
|
|
70
|
+
# By default token type used in authorizaion header
|
|
71
|
+
DEFAULT_TOKEN_TYPE = 'Bearer'
|
|
72
|
+
|
|
67
73
|
# The response format appended to the path and sent in the 'Accept' header if none is set
|
|
68
74
|
#
|
|
69
75
|
# @note JSON is the only available format at this time
|
|
@@ -81,7 +87,7 @@ module WrAPI
|
|
|
81
87
|
# It uses the DefaultPager class from the WrAPI::RequestPagination module.
|
|
82
88
|
DEFAULT_PAGINATION = WrAPI::RequestPagination::DefaultPager
|
|
83
89
|
|
|
84
|
-
attr_accessor
|
|
90
|
+
attr_accessor(*VALID_OPTIONS_KEYS)
|
|
85
91
|
|
|
86
92
|
# When this module is extended, set all configuration options to their default values
|
|
87
93
|
def self.extended(base)
|
|
@@ -103,7 +109,6 @@ module WrAPI
|
|
|
103
109
|
# Reset all configuration options to defaults
|
|
104
110
|
def reset
|
|
105
111
|
self.access_token = nil
|
|
106
|
-
self.token_type = nil
|
|
107
112
|
self.refresh_token = nil
|
|
108
113
|
self.token_expires = nil
|
|
109
114
|
self.client_id = nil
|
|
@@ -111,8 +116,11 @@ module WrAPI
|
|
|
111
116
|
self.username = nil
|
|
112
117
|
self.password = nil
|
|
113
118
|
self.endpoint = nil
|
|
114
|
-
|
|
119
|
+
self.rate_limit = nil
|
|
120
|
+
self.rate_period = nil
|
|
115
121
|
self.logger = nil
|
|
122
|
+
|
|
123
|
+
self.token_type = DEFAULT_TOKEN_TYPE
|
|
116
124
|
self.connection_options = DEFAULT_CONNECTION_OPTIONS
|
|
117
125
|
self.format = DEFAULT_FORMAT
|
|
118
126
|
self.page_size = DEFAULT_PAGE_SIZE
|
data/lib/wrapi/connection.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'faraday'
|
|
4
|
+
require File.expand_path('middleware/rate_throttle_middleware', __dir__)
|
|
4
5
|
|
|
5
6
|
module WrAPI
|
|
6
7
|
# @private
|
|
@@ -42,8 +43,8 @@ module WrAPI
|
|
|
42
43
|
setup_headers(connection)
|
|
43
44
|
connection.response :json, content_type: /\bjson$/
|
|
44
45
|
connection.use Faraday::Request::UrlEncoded
|
|
45
|
-
|
|
46
46
|
setup_logger_filtering(connection, logger) if logger
|
|
47
|
+
connection.use WrAPI::RateThrottleMiddleware, limit: rate_limit, period: rate_period if rate_limit && rate_period
|
|
47
48
|
end
|
|
48
49
|
end
|
|
49
50
|
|
|
@@ -73,7 +74,7 @@ module WrAPI
|
|
|
73
74
|
# @return [void]
|
|
74
75
|
# @note The authorization header will only be set if the access_token is present.
|
|
75
76
|
def setup_authorization(connection)
|
|
76
|
-
connection.headers['Authorization'] = "
|
|
77
|
+
connection.headers['Authorization'] = "#{token_type} #{access_token}" if access_token && token_type
|
|
77
78
|
end
|
|
78
79
|
|
|
79
80
|
# Sets up the headers for the given connection. Override to set own headers.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'faraday'
|
|
4
|
+
|
|
5
|
+
module WrAPI
|
|
6
|
+
# A Faraday middleware for rate limiting requests.
|
|
7
|
+
#
|
|
8
|
+
# This middleware ensures that the number of requests made through a Faraday connection
|
|
9
|
+
# does not exceed a specified limit within a given time period.
|
|
10
|
+
#
|
|
11
|
+
# @example Add middleware to a Faraday connection
|
|
12
|
+
# connection = Faraday.new(url: 'https://api.example.com') do |faraday|
|
|
13
|
+
# faraday.use RateThrottleMiddleware, limit: 300, period: 60
|
|
14
|
+
# faraday.adapter Faraday.default_adapter
|
|
15
|
+
# end
|
|
16
|
+
#
|
|
17
|
+
# @see https://github.com/lostisland/faraday Faraday Documentation
|
|
18
|
+
#
|
|
19
|
+
class RateThrottleMiddleware < Faraday::Middleware
|
|
20
|
+
# Initializes the RateThrottleMiddleware.
|
|
21
|
+
#
|
|
22
|
+
# @param app [#call] The next middleware or the actual Faraday adapter.
|
|
23
|
+
# @param limit [Integer] The maximum number of requests allowed within the specified period. Default is 300.
|
|
24
|
+
# @param period [Integer] The time period in seconds over which the limit applies. Default is 60 seconds.
|
|
25
|
+
#
|
|
26
|
+
# @example
|
|
27
|
+
# middleware = RateThrottleMiddleware.new(app, limit: 300, period: 60)
|
|
28
|
+
#
|
|
29
|
+
def initialize(app, limit: 300, period: 60)
|
|
30
|
+
super(app)
|
|
31
|
+
@limit = limit
|
|
32
|
+
@period = period
|
|
33
|
+
@requests = []
|
|
34
|
+
@mutex = Mutex.new
|
|
35
|
+
@condition = ConditionVariable.new
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def call(env)
|
|
39
|
+
throttle_request
|
|
40
|
+
@app.call(env)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
private
|
|
44
|
+
|
|
45
|
+
def throttle_request
|
|
46
|
+
@mutex.synchronize do
|
|
47
|
+
now = Time.now.to_f
|
|
48
|
+
remove_expired_requests(now)
|
|
49
|
+
|
|
50
|
+
rate_limited(now)
|
|
51
|
+
|
|
52
|
+
# Record the new request
|
|
53
|
+
@requests.push(Time.now.to_f)
|
|
54
|
+
@condition.broadcast
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def remove_expired_requests(now)
|
|
59
|
+
# Clear requests older than the rate limit period
|
|
60
|
+
@requests.pop while !@requests.empty? && @requests[0] < (now - @period)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def rate_limited(now)
|
|
64
|
+
# Wait if the request limit is reached
|
|
65
|
+
while @requests.size >= @limit
|
|
66
|
+
sleep_time = @requests[0] + @period - now
|
|
67
|
+
@condition.wait(@mutex, sleep_time) if sleep_time.positive?
|
|
68
|
+
remove_expired_requests(Time.now.to_f)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
data/lib/wrapi/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: wrapi
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Janco Tanis
|
|
8
8
|
bindir: exe
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2025-
|
|
10
|
+
date: 2025-11-11 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: faraday
|
|
@@ -96,6 +96,7 @@ files:
|
|
|
96
96
|
- lib/wrapi/configuration.rb
|
|
97
97
|
- lib/wrapi/connection.rb
|
|
98
98
|
- lib/wrapi/entity.rb
|
|
99
|
+
- lib/wrapi/middleware/rate_throttle_middleware.rb
|
|
99
100
|
- lib/wrapi/pagination.rb
|
|
100
101
|
- lib/wrapi/request.rb
|
|
101
102
|
- lib/wrapi/respond_to.rb
|