tiny-rest-client 0.2.1 → 0.3.0
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 +8 -1
- data/README.md +49 -11
- data/lib/tiny_rest_client/middleware/retry.rb +39 -0
- data/lib/tiny_rest_client/request.rb +6 -4
- data/lib/tiny_rest_client/response.rb +9 -2
- data/lib/tiny_rest_client/version.rb +1 -1
- data/lib/tiny_rest_client.rb +17 -3
- 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: 72d74c14f37ab28b47e2c0cf52bfa9f092d2457bad0d5487bbcbb32f1c5b12d5
|
|
4
|
+
data.tar.gz: 49eac5d225c02dd3675d1c90a41d71067fa150cebb0018d5126d2c8b0e19102e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ee2b67e844a132f1d549cf814098d4af9592884d7a61723391fe98774d50c525b7ba346c59bd2fdfe27d0e2ba869071ca59402c473aac1438c1791cf4d1ca94f
|
|
7
|
+
data.tar.gz: b02d9ffc1f3e6601a942a7e6f4f2fa752f4e580fca1a7fee3a243887eb2fd9246813bc7372fa0a35416a27784969f6178cde4973f0a5985237740845dc28b7e7
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- Class-level retries with configurable delay (throttling)
|
|
12
|
+
- `retries 3, delay: 0.5` - retry 3 times on 5xx errors with 500ms delay between attempts
|
|
13
|
+
- Default retryable codes: 500, 502, 503, 504
|
|
14
|
+
- Instance-level override supported
|
|
15
|
+
|
|
8
16
|
## [0.2.1] - 2026-03-03
|
|
9
17
|
|
|
10
18
|
### Fixed
|
|
@@ -18,7 +26,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
18
26
|
- Supports nested client names (e.g. `api/v1/stripe`)
|
|
19
27
|
- Optional base URL argument
|
|
20
28
|
- Configurable root namespace via `--namespace`
|
|
21
|
-
- Automatically generates properly namespaced client classes under `app/`
|
|
22
29
|
|
|
23
30
|
## [0.1.0] - 2026-02-22
|
|
24
31
|
|
data/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# TinyRestClient
|
|
2
2
|
|
|
3
|
-
A minimal
|
|
3
|
+
A minimal HTTP client wrapper for Rails, built on top of Typhoeus. Perfect for quickly building clean, opinionated API clients with almost no boilerplate.
|
|
4
4
|
|
|
5
5
|
### Features
|
|
6
6
|
|
|
@@ -22,6 +22,7 @@ A minimal, opinionated HTTP client wrapper for Rails, built on top of Typhoeus.
|
|
|
22
22
|
- [Rails Generator](#rails-generator)
|
|
23
23
|
- [Configuration](#configuration)
|
|
24
24
|
- [Authorization](#authorization)
|
|
25
|
+
- [Retries & Delay (Throttling)](#retries--delay-throttling)
|
|
25
26
|
- [Making Requests](#making-requests)
|
|
26
27
|
- [Response Handling](#response-handling)
|
|
27
28
|
- [Contributing](#contributing)
|
|
@@ -32,7 +33,7 @@ A minimal, opinionated HTTP client wrapper for Rails, built on top of Typhoeus.
|
|
|
32
33
|
Add this line to your Gemfile:
|
|
33
34
|
|
|
34
35
|
```bash
|
|
35
|
-
gem "tiny-rest-client"
|
|
36
|
+
gem "tiny-rest-client"
|
|
36
37
|
```
|
|
37
38
|
|
|
38
39
|
Or install it manually:
|
|
@@ -57,7 +58,7 @@ class MyClient < TinyRestClient::Core
|
|
|
57
58
|
# pass bunch of headers (optional)
|
|
58
59
|
headers "User-Agent": "MyTest/1.0", "Accept": "application/json"
|
|
59
60
|
|
|
60
|
-
# define actions
|
|
61
|
+
# define actions (optional)
|
|
61
62
|
def fetch_todos(**)
|
|
62
63
|
get("/todos", **)
|
|
63
64
|
end
|
|
@@ -84,7 +85,7 @@ client = MyClient.new
|
|
|
84
85
|
client.fetch_todos(page: 1, per_page: 20)
|
|
85
86
|
client.fetch_todo(1)
|
|
86
87
|
client.create_todo(name: "Custom")
|
|
87
|
-
client.update_todo(status: "finished")
|
|
88
|
+
client.update_todo(1, { status: "finished" })
|
|
88
89
|
client.destroy_todo(1)
|
|
89
90
|
```
|
|
90
91
|
|
|
@@ -98,11 +99,11 @@ rails generate tiny_rest_client:client NAME [URL] [options]
|
|
|
98
99
|
|
|
99
100
|
### Available options
|
|
100
101
|
|
|
101
|
-
| Option | Default | Description |
|
|
102
|
-
|
|
103
|
-
| NAME | (required) | Client name (supports nesting like `api/v1/stripe`) |
|
|
102
|
+
| Option | Default | Description |
|
|
103
|
+
|-----------------|---------------|-------------------------------------------------------------|
|
|
104
|
+
| NAME | (required) | Client name (supports nesting like `api/v1/stripe`) |
|
|
104
105
|
| URL | (none) | Base API URL | `rails g ... stripe https://api.stripe.com` |
|
|
105
|
-
| --namespace | `clients` | Root folder under `app/` (e.g. `app/services
|
|
106
|
+
| --namespace | `clients` | Root folder under `app/` (e.g. `app/services/`) |
|
|
106
107
|
|
|
107
108
|
### Basic usage
|
|
108
109
|
|
|
@@ -128,7 +129,7 @@ You can configure client setup at the class level:
|
|
|
128
129
|
class MyClient < TinyRestClient::Core
|
|
129
130
|
api_path "https://api.example.com/v1"
|
|
130
131
|
authorization :bearer, token: "your_token"
|
|
131
|
-
headers "Accept": "application/json", "User-Agent"
|
|
132
|
+
headers "Accept": "application/json", "User-Agent": "MyApp/1.0"
|
|
132
133
|
end
|
|
133
134
|
|
|
134
135
|
client = MyClient.new
|
|
@@ -207,6 +208,40 @@ end
|
|
|
207
208
|
MyClient.new(auth: { basic_auth: { user: "name", password: "secret" } })
|
|
208
209
|
```
|
|
209
210
|
|
|
211
|
+
## Retries & Delay (Throttling)
|
|
212
|
+
|
|
213
|
+
The library supports automatic retries on server errors and a simple fixed delay (throttling) between requests, both configurable at class or instance level.
|
|
214
|
+
|
|
215
|
+
### Retries
|
|
216
|
+
|
|
217
|
+
Retries only happen on configurable HTTP status codes (default: 500, 502, 503, 504).
|
|
218
|
+
|
|
219
|
+
```ruby
|
|
220
|
+
class MyClient < TinyRestClient::Core
|
|
221
|
+
# retry 3 times on default 5xx errors
|
|
222
|
+
retries 3
|
|
223
|
+
|
|
224
|
+
# custom retryable codes
|
|
225
|
+
retries 5, on: [500..599]
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
# per-instance
|
|
229
|
+
client = MyClient.new(retries: { count: 3, on: [500..599] })
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Delay (Throttling)
|
|
233
|
+
|
|
234
|
+
Add a fixed delay (seconds) between each request - useful for rate-limited APIs (default: 1.0 second).
|
|
235
|
+
|
|
236
|
+
```ruby
|
|
237
|
+
class MyClient < TinyRestClient::Core
|
|
238
|
+
retries 3, delay: 1.0 # wait 1 second between every retry
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
# per-instance
|
|
242
|
+
client = MyClient.new(retries: { count: 3, delay: 1.0 })
|
|
243
|
+
```
|
|
244
|
+
|
|
210
245
|
## Making Requests
|
|
211
246
|
|
|
212
247
|
The standard HTTP methods are available directly on every client instance automatically include any headers or authorization configuration you defined.
|
|
@@ -231,14 +266,16 @@ helpers:
|
|
|
231
266
|
|--------|-------------|
|
|
232
267
|
| success? | Helper that represent successful response. |
|
|
233
268
|
| failure? | The opposite. |
|
|
269
|
+
| timed_out? | Returns request timeout status |
|
|
234
270
|
| code | HTTP status code (e.g. `200`, `404`). |
|
|
235
|
-
| status |
|
|
271
|
+
| status | Returns code symbol (e.g. `:ok`, `:couldnt_connect`). |
|
|
236
272
|
| headers | Hash of response headers (keys are not normalized). |
|
|
237
273
|
| body | Auto-parsed JSON (symbolized keys). If parsing fails, returns the original raw string. |
|
|
238
274
|
|
|
239
275
|
```ruby
|
|
240
276
|
response.success? # true if code 200–299
|
|
241
277
|
response.failure? # opposite
|
|
278
|
+
response.timed_out? # Typhoeus timed_out status
|
|
242
279
|
response.code # HTTP status code
|
|
243
280
|
response.status # Typhoeus return_code symbol
|
|
244
281
|
response.body # auto-parsed JSON hash or raw string
|
|
@@ -251,8 +288,9 @@ TinyRestClient does not raise exceptions for HTTP status codes.
|
|
|
251
288
|
|
|
252
289
|
Network-level errors (timeouts, connection failures, etc.) are reflected in:
|
|
253
290
|
|
|
254
|
-
* response.status
|
|
255
291
|
* response.success? / response.failure?
|
|
292
|
+
* response.timed_out?
|
|
293
|
+
* response.status
|
|
256
294
|
|
|
257
295
|
This makes error handling explicit and predictable.
|
|
258
296
|
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Middleware
|
|
4
|
+
module Retry
|
|
5
|
+
DEFAULT_OPTIONS = {
|
|
6
|
+
count: 0, # 0 = no retries by default
|
|
7
|
+
on: [500, 502, 503, 504], # only these server errors by default
|
|
8
|
+
delay: 1.0 # 1 second between retries by default
|
|
9
|
+
}.freeze
|
|
10
|
+
|
|
11
|
+
def self.call(request, options = {})
|
|
12
|
+
opts = DEFAULT_OPTIONS.merge(options)
|
|
13
|
+
attempt = 0
|
|
14
|
+
|
|
15
|
+
loop do
|
|
16
|
+
attempt += 1
|
|
17
|
+
|
|
18
|
+
begin
|
|
19
|
+
response = request.run
|
|
20
|
+
return response if response.success?
|
|
21
|
+
|
|
22
|
+
if attempt <= opts[:count] && opts[:on].include?(response.code)
|
|
23
|
+
sleep opts[:delay].to_f
|
|
24
|
+
next
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
return response
|
|
28
|
+
rescue Typhoeus::Errors::TyphoeusError => e
|
|
29
|
+
if attempt <= opts[:count]
|
|
30
|
+
sleep opts[:delay].to_f
|
|
31
|
+
retry
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
raise Typhoeus::Errors::TyphoeusError, e
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
class Request
|
|
4
|
-
attr_reader :method, :api_path, :headers, :body, :params, :endpoint, :rest
|
|
4
|
+
attr_reader :method, :api_path, :headers, :body, :params, :endpoint, :retries, :rest
|
|
5
5
|
|
|
6
|
-
def initialize(method, api_path, endpoint: "", headers: nil, auth_config: nil, body: nil, params: nil)
|
|
6
|
+
def initialize(method, api_path, endpoint: "", headers: nil, auth_config: nil, body: nil, params: nil, retries: nil)
|
|
7
7
|
@method = method || :get
|
|
8
8
|
@api_path = api_path || raise(ArgumentError, "Define api_path base URL")
|
|
9
9
|
@endpoint = endpoint
|
|
10
10
|
@headers = headers
|
|
11
11
|
@body = body
|
|
12
12
|
@params = params
|
|
13
|
+
@retries = retries
|
|
13
14
|
@rest = {}
|
|
14
15
|
|
|
15
16
|
configure_auth(auth_config)
|
|
@@ -20,7 +21,8 @@ class Request
|
|
|
20
21
|
code: response.code,
|
|
21
22
|
status: response.return_code,
|
|
22
23
|
body: response.body,
|
|
23
|
-
headers: response.headers
|
|
24
|
+
headers: response.headers,
|
|
25
|
+
timed_out: response.timed_out?
|
|
24
26
|
)
|
|
25
27
|
rescue Typhoeus::Errors::TyphoeusError => e
|
|
26
28
|
Response.new(
|
|
@@ -48,6 +50,6 @@ class Request
|
|
|
48
50
|
end
|
|
49
51
|
|
|
50
52
|
def response
|
|
51
|
-
@response ||= request
|
|
53
|
+
@response ||= Middleware::Retry.call(request, retries)
|
|
52
54
|
end
|
|
53
55
|
end
|
|
@@ -3,13 +3,14 @@
|
|
|
3
3
|
# The Response class represents a response object that
|
|
4
4
|
# can be used to represent success or failure outcomes
|
|
5
5
|
class Response
|
|
6
|
-
attr_reader :code, :status, :body, :headers
|
|
6
|
+
attr_reader :code, :status, :body, :headers, :timed_out
|
|
7
7
|
|
|
8
|
-
def initialize(code: nil, status: nil, body: nil, headers: nil)
|
|
8
|
+
def initialize(code: nil, status: nil, body: nil, headers: nil, timed_out: false)
|
|
9
9
|
@code = code&.to_i
|
|
10
10
|
@status = status
|
|
11
11
|
@headers = headers
|
|
12
12
|
@body = parse_body(body)
|
|
13
|
+
@timed_out = timed_out
|
|
13
14
|
end
|
|
14
15
|
|
|
15
16
|
def success?
|
|
@@ -20,6 +21,12 @@ class Response
|
|
|
20
21
|
!success?
|
|
21
22
|
end
|
|
22
23
|
|
|
24
|
+
def timed_out?
|
|
25
|
+
timed_out
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
23
30
|
def parse_body(raw_body)
|
|
24
31
|
return raw_body unless raw_body.is_a?(String)
|
|
25
32
|
|
data/lib/tiny_rest_client.rb
CHANGED
|
@@ -8,6 +8,7 @@ require "tiny_rest_client/strategies/auth/basic_auth"
|
|
|
8
8
|
require "tiny_rest_client/strategies/auth/bearer"
|
|
9
9
|
require "tiny_rest_client/strategies/auth/api_key"
|
|
10
10
|
require "tiny_rest_client/strategies/auth/registry"
|
|
11
|
+
require "tiny_rest_client/middleware/retry"
|
|
11
12
|
require "tiny_rest_client/request"
|
|
12
13
|
require "tiny_rest_client/response"
|
|
13
14
|
require "tiny_rest_client/version"
|
|
@@ -44,14 +45,27 @@ module TinyRestClient
|
|
|
44
45
|
@headers || {}
|
|
45
46
|
end
|
|
46
47
|
end
|
|
48
|
+
|
|
49
|
+
def retries(count = nil, on: nil, delay: nil)
|
|
50
|
+
if count.nil?
|
|
51
|
+
@retry_options ||= Middleware::Retry::DEFAULT_OPTIONS.dup
|
|
52
|
+
else
|
|
53
|
+
@retry_options = {
|
|
54
|
+
count: count || Middleware::Retry::DEFAULT_OPTIONS[:count],
|
|
55
|
+
on: Array(on || Middleware::Retry::DEFAULT_OPTIONS[:on]),
|
|
56
|
+
delay: delay || Middleware::Retry::DEFAULT_OPTIONS[:delay]
|
|
57
|
+
}
|
|
58
|
+
end
|
|
59
|
+
end
|
|
47
60
|
end
|
|
48
61
|
|
|
49
|
-
attr_reader :api_path, :auth_config, :headers
|
|
62
|
+
attr_reader :api_path, :auth_config, :headers, :retries
|
|
50
63
|
|
|
51
|
-
def initialize(api_path: nil, auth: nil, headers: {})
|
|
64
|
+
def initialize(api_path: nil, auth: nil, headers: {}, retries: nil)
|
|
52
65
|
@api_path = api_path || self.class.api_path || raise(ArgumentError, "Undefined api_path base URL")
|
|
53
66
|
@auth_config = auth || self.class.authorization
|
|
54
67
|
@headers = merge_headers(headers)
|
|
68
|
+
@retries = retries || self.class.retries
|
|
55
69
|
end
|
|
56
70
|
|
|
57
71
|
def head(endpoint, params = {})
|
|
@@ -89,7 +103,7 @@ module TinyRestClient
|
|
|
89
103
|
end
|
|
90
104
|
|
|
91
105
|
def common_params
|
|
92
|
-
{ headers:, auth_config: }
|
|
106
|
+
{ headers:, auth_config:, retries: }.compact_blank
|
|
93
107
|
end
|
|
94
108
|
end
|
|
95
109
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: tiny-rest-client
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dabrovski
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-03-
|
|
11
|
+
date: 2026-03-19 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: typhoeus
|
|
@@ -41,6 +41,7 @@ files:
|
|
|
41
41
|
- lib/generators/tiny_rest_client/templates/client_test.rb.tt
|
|
42
42
|
- lib/tiny-rest-client.rb
|
|
43
43
|
- lib/tiny_rest_client.rb
|
|
44
|
+
- lib/tiny_rest_client/middleware/retry.rb
|
|
44
45
|
- lib/tiny_rest_client/railtie.rb
|
|
45
46
|
- lib/tiny_rest_client/request.rb
|
|
46
47
|
- lib/tiny_rest_client/response.rb
|