rest-client-wrapper 3.0.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 +7 -0
- data/README.md +484 -0
- data/lib/rest_client_wrapper.rb +33 -0
- data/lib/rest_client_wrapper/authenticators/auth.rb +30 -0
- data/lib/rest_client_wrapper/authenticators/basic.rb +45 -0
- data/lib/rest_client_wrapper/authenticators/custom.rb +61 -0
- data/lib/rest_client_wrapper/authenticators/oauth.rb +90 -0
- data/lib/rest_client_wrapper/authenticators/token.rb +43 -0
- data/lib/rest_client_wrapper/constants.rb +28 -0
- data/lib/rest_client_wrapper/exceptions.rb +37 -0
- data/lib/rest_client_wrapper/http.rb +66 -0
- data/lib/rest_client_wrapper/paginators/echo.rb +67 -0
- data/lib/rest_client_wrapper/paginators/echo_paginator.rb +67 -0
- data/lib/rest_client_wrapper/paginators/header_link.rb +78 -0
- data/lib/rest_client_wrapper/paginators/header_link_paginator.rb +78 -0
- data/lib/rest_client_wrapper/paginators/paginate.rb +32 -0
- data/lib/rest_client_wrapper/request.rb +75 -0
- data/lib/rest_client_wrapper/response.rb +34 -0
- data/lib/rest_client_wrapper/rest_client.rb +178 -0
- data/lib/rest_client_wrapper/version.rb +23 -0
- data/rest-client-wrapper.gemspec +51 -0
- data/spec/authenticators/oauth_spec.rb +103 -0
- data/spec/factories/request.rb +48 -0
- data/spec/factories/response.rb +47 -0
- data/spec/request_spec.rb +185 -0
- data/spec/rest_client_spec.rb +249 -0
- data/spec/spec_helper.rb +75 -0
- data/spec/support/factory_bot.rb +28 -0
- data/spec/support/stub_helper.rb +20 -0
- metadata +216 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: def40a893f9c570b65d5bee0bb033b6c20788a4efb4a88f6f0b9bc5c6c732bd1
|
4
|
+
data.tar.gz: f4b4e68fb5aae3c0d5b8dcd2f8eb1feeb807f7c15753e2394c2bbfeae637e26d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2d6a4ff99f8181e0b66df0097b179af79f45d655ee432946f1ecd6c4dd3722bedd7d9e741442246e4f14c86fbc74f792578585840f55d24f8c9ab89f897e1542
|
7
|
+
data.tar.gz: 696d1b57674536173f903913745989bec8f520c83398d0f846e829f6589eeaaf008d8c5d0690072285c487ed6f718d80c94c16d9327ff36e44babc42e246181d
|
data/README.md
ADDED
@@ -0,0 +1,484 @@
|
|
1
|
+
# Rest-Client-Wrapper
|
2
|
+
|
3
|
+
REST client wrapper around the rest-client gem: https://github.com/rest-client/rest-client
|
4
|
+
|
5
|
+
Features:
|
6
|
+
|
7
|
+
- Retries for response codes: 401 & 429; additional response codes can be added through configuration
|
8
|
+
- Authentication for: Basic, OAuth, Token; plus a Custom authenticator
|
9
|
+
- Re-authentication for: OAuth
|
10
|
+
- URI segment construction
|
11
|
+
- Pagination for: Header links and Echo
|
12
|
+
|
13
|
+
---
|
14
|
+
## Table of contents
|
15
|
+
1. [ Get Started ](#get-started)
|
16
|
+
2. [ Rest-Client ](#rest-client)
|
17
|
+
3. [ Authentication ](#authentication)
|
18
|
+
4. [ Paginator ](#paginator)
|
19
|
+
5. [ Request ](#request)
|
20
|
+
6. [ Response ](#response)
|
21
|
+
7. [ Examples ](#examples)
|
22
|
+
|
23
|
+
<a name="get-started"></a>
|
24
|
+
# Get Started
|
25
|
+
|
26
|
+
## Create a rest_client
|
27
|
+
|
28
|
+
A `rest_client` must be created to make requests (if the rest_client requires authentication, an authenticator can be set - see _Authentication_):
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
require "rest_client_wrapper"
|
32
|
+
|
33
|
+
# Create a rest_client
|
34
|
+
rest_client = RestClientWrapper::RestClient.new({ host: "https://www.host.com" })
|
35
|
+
```
|
36
|
+
|
37
|
+
## Basic Usage: `make_request`
|
38
|
+
|
39
|
+
The `rest_client` can make HTTP requests using `make_request`:
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
# Make a request
|
43
|
+
response = rest_client.make_request({ http_method: :get, uri: "https://www.host.com" })
|
44
|
+
```
|
45
|
+
<a name="get_started"></a>
|
46
|
+
## Basic Usage: `execute`
|
47
|
+
|
48
|
+
The `rest_client` can also make HTTP requests using `execute`, which accepts a _Request_ object. The advantage of this approach is that the URI with the _segment parameters_ is automatically built.
|
49
|
+
|
50
|
+
_Segment parameters_ can be added to an existing `request`:
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
# Create an HTTP request with a segmented uri
|
54
|
+
request = Request.new({ http_method: :get, uri: "/%<segment_1>s/%<segment_2>s" })
|
55
|
+
|
56
|
+
# Add the segment parameter(s) to the request ('%<segment_x>s' in the uri will be replaced with the matching segment param when the request is executed)
|
57
|
+
request.segment_params = { segment_1: "user_id_0001", segment_2: "course_id_0001" }
|
58
|
+
|
59
|
+
# Execute a request
|
60
|
+
response = rest_client.execute({ request: request })
|
61
|
+
```
|
62
|
+
|
63
|
+
_Segment parameters_ can be created with the `request`:
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
# Segment parameters can be created with the request
|
67
|
+
request = Request.new({ http_method: :post, uri: "/%<segment_1>s", segment_params: { segment_1: "user_id_0001" }, payload: { first_name: "name" }, headers: { content_type: "application/json" } })
|
68
|
+
|
69
|
+
# Execute a request
|
70
|
+
response = rest_client.execute({ request: request })
|
71
|
+
```
|
72
|
+
<a name="authentication"></a>
|
73
|
+
## Authentication
|
74
|
+
|
75
|
+
The `rest_client` can make authenticated HTTP requests using an `authenticator`.
|
76
|
+
|
77
|
+
### Basic
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
# Add a Basic authenticator to the rest_client
|
81
|
+
rest_client.authenticator = Authenticator::Basic.new({ username: "username", password: "password" })
|
82
|
+
|
83
|
+
# Make a request
|
84
|
+
response = rest_client.make_request({ http_method: :get, uri: "https://www.host.com/api/v1/resource" })
|
85
|
+
```
|
86
|
+
|
87
|
+
### Custom
|
88
|
+
|
89
|
+
`new` accepts the following parameters:
|
90
|
+
- type
|
91
|
+
- custom_auth_param
|
92
|
+
|
93
|
+
```ruby
|
94
|
+
# Add a Custom authenticator using query_param
|
95
|
+
# The custom auth parameter will be added as a query parameter
|
96
|
+
rest_client.authenticator = Authenticator::Custom.new({ type: :query_param, auth_param: { custom_auth_param: "auth_value" } })
|
97
|
+
|
98
|
+
# Make a request
|
99
|
+
response = rest_client.make_request({ http_method: :get, uri: "https://www.host.com/api/v1/resource" })
|
100
|
+
```
|
101
|
+
|
102
|
+
```ruby
|
103
|
+
# Add a Custom authenticator using header
|
104
|
+
# The custom auth parameter will be added to the request header
|
105
|
+
rest_client.authenticator = Authenticator::Custom.new({ type: :header, auth_param: { custom_auth_param: "auth_value" } })
|
106
|
+
|
107
|
+
# Make a request
|
108
|
+
response = rest_client.make_request({ http_method: :get, uri: "https://www.host.com/api/v1/resource" })
|
109
|
+
```
|
110
|
+
|
111
|
+
### OAuth
|
112
|
+
|
113
|
+
```ruby
|
114
|
+
# Add an OAuth authenticator to the rest_client
|
115
|
+
rest_client.authenticator = Authenticator::Oauth.new({ site: "https://www.host.com", token_url_path: "token_url_path", client_id: "client_id", client_secret: "secret" })
|
116
|
+
|
117
|
+
# Make a request
|
118
|
+
response = rest_client.make_request({ http_method: :get, uri: "/api/v1/user" })
|
119
|
+
```
|
120
|
+
|
121
|
+
### Token
|
122
|
+
|
123
|
+
```ruby
|
124
|
+
# Add a Token authenticator to the rest_client
|
125
|
+
rest_client.authenticator = Authenticator::Token.new({ access_token: "access_token" })
|
126
|
+
|
127
|
+
# Make a request
|
128
|
+
response = rest_client.make_request({ http_method: :get, uri: "/api/v1/user" })
|
129
|
+
```
|
130
|
+
|
131
|
+
## Pagination
|
132
|
+
|
133
|
+
The `rest_client` can make paginated HTTP requests using a `paginator`.
|
134
|
+
|
135
|
+
### Header links
|
136
|
+
|
137
|
+
```ruby
|
138
|
+
# Add a Header links paginator to the rest_client
|
139
|
+
rest_client.paginator = Paginator::HeaderLink.new
|
140
|
+
|
141
|
+
# Make a request for paginated data
|
142
|
+
rest_client.make_request_for_pages({ http_method: :get, uri: "/api/v1/user" })
|
143
|
+
```
|
144
|
+
|
145
|
+
### Echo360
|
146
|
+
|
147
|
+
```ruby
|
148
|
+
# Add an Echo paginator to the rest_client
|
149
|
+
rest_client.paginator = Paginator::Echo.new
|
150
|
+
|
151
|
+
rest_client.make_request_for_pages({ http_method: :get, uri: "/api/v1/user" })
|
152
|
+
```
|
153
|
+
|
154
|
+
---
|
155
|
+
|
156
|
+
<a name="rest-client"></a>
|
157
|
+
# `rest_client`
|
158
|
+
|
159
|
+
`rest_client` has the following accessors:
|
160
|
+
|
161
|
+
- authenticator
|
162
|
+
- paginator
|
163
|
+
|
164
|
+
`rest_client` has the following methods:
|
165
|
+
|
166
|
+
## new
|
167
|
+
|
168
|
+
`new` accepts the following parameters:
|
169
|
+
|
170
|
+
- host
|
171
|
+
- config (optional)
|
172
|
+
|
173
|
+
`new` returns a _Client_ object.
|
174
|
+
|
175
|
+
### Configuration
|
176
|
+
|
177
|
+
_Client_ provides the following default configuration:
|
178
|
+
|
179
|
+
```ruby
|
180
|
+
config = {
|
181
|
+
retries: {
|
182
|
+
401 => { max_retry: 1, wait: 0 }, # Unauthorized
|
183
|
+
429 => { max_retry: 3, wait: 3 } # Too Many Requests
|
184
|
+
}
|
185
|
+
}
|
186
|
+
|
187
|
+
rest_client = RestClientWrapper::RestClient.new({ host: "host" })
|
188
|
+
```
|
189
|
+
|
190
|
+
If the caller wishes for additional HTTP codes to be handled, they can be specified in the `config`:
|
191
|
+
|
192
|
+
```ruby
|
193
|
+
config = {
|
194
|
+
retries: {
|
195
|
+
431 => { max_retry: 2, wait: 1 }, # Request Header Fields Too Large
|
196
|
+
500 => { max_retry: 2, wait: 1 } # Internal Server Error
|
197
|
+
}
|
198
|
+
}
|
199
|
+
|
200
|
+
rest_client = RestClientWrapper::RestClient.new({ host: "host", config: config })
|
201
|
+
```
|
202
|
+
|
203
|
+
## make_request
|
204
|
+
|
205
|
+
`make_request` accepts the following parameters:
|
206
|
+
|
207
|
+
- http_method
|
208
|
+
- uri
|
209
|
+
- payload (optional)
|
210
|
+
- query_params (optional)
|
211
|
+
- headers (optional)
|
212
|
+
|
213
|
+
`make_request` returns a _Response_ object.
|
214
|
+
|
215
|
+
## make_request_for_pages
|
216
|
+
|
217
|
+
`make_request_for_pages` accepts the following parameters:
|
218
|
+
|
219
|
+
- http_method
|
220
|
+
- uri
|
221
|
+
- query_params (optional)
|
222
|
+
- headers (optional)
|
223
|
+
- data (optional)
|
224
|
+
|
225
|
+
`make_request_for_pages` returns:
|
226
|
+
|
227
|
+
- an array where each element is a _Response_ object for each page (ie header and the body), if data is false.
|
228
|
+
- an array where each element is one entity from every `response.body` for each page (ie the data), if data is true.
|
229
|
+
|
230
|
+
## execute
|
231
|
+
|
232
|
+
`execute` accepts the following parameters:
|
233
|
+
|
234
|
+
- request
|
235
|
+
|
236
|
+
`execute` returns a _Response_ object.
|
237
|
+
|
238
|
+
# `Authenticator`
|
239
|
+
|
240
|
+
`authenticator` has the following methods:
|
241
|
+
|
242
|
+
## generate_auth
|
243
|
+
|
244
|
+
`generate_auth` returns a hash that is suitable for use in a _Request_.
|
245
|
+
|
246
|
+
## `Basic`
|
247
|
+
|
248
|
+
## new
|
249
|
+
|
250
|
+
`new` accepts the following parameters:
|
251
|
+
|
252
|
+
- username
|
253
|
+
- password
|
254
|
+
|
255
|
+
`new` returns a _Basic_ (_Authenticator_) object.
|
256
|
+
|
257
|
+
## `Custom`
|
258
|
+
|
259
|
+
## new
|
260
|
+
|
261
|
+
`new` accepts the following parameters:
|
262
|
+
|
263
|
+
- type
|
264
|
+
- auth_param
|
265
|
+
|
266
|
+
`new` returns a _Custom_ (_Authenticator_) object.
|
267
|
+
|
268
|
+
## `Oauth`
|
269
|
+
|
270
|
+
## new
|
271
|
+
|
272
|
+
`new` accepts the following parameters:
|
273
|
+
|
274
|
+
- site
|
275
|
+
- token_url_path
|
276
|
+
- client_id
|
277
|
+
- client_secret
|
278
|
+
|
279
|
+
`new` returns an _Oauth_ (_Authenticator_) object.
|
280
|
+
|
281
|
+
## `Token`
|
282
|
+
|
283
|
+
## new
|
284
|
+
|
285
|
+
`new` accepts the following parameters:
|
286
|
+
|
287
|
+
- access_token
|
288
|
+
|
289
|
+
`new` returns a _Token_ (_Authenticator_) object.
|
290
|
+
|
291
|
+
## tokens
|
292
|
+
|
293
|
+
`tokens` returns all of the token(s) for the `authenticator`.
|
294
|
+
|
295
|
+
## access_token
|
296
|
+
|
297
|
+
`access_token` returns the access token for the `client_id` of the `authenticator`.
|
298
|
+
|
299
|
+
## Oauth.authenticate
|
300
|
+
|
301
|
+
`authenticate` accepts the following parameters:
|
302
|
+
|
303
|
+
- client_id
|
304
|
+
- access_token
|
305
|
+
|
306
|
+
`authenticate` authenticates the rest_client using the `client_id` and `access_token` and updates the `tokens` for the rest_client.
|
307
|
+
|
308
|
+
<a name="paginator"></a>
|
309
|
+
# `Paginator`
|
310
|
+
|
311
|
+
`paginator` has the following accessors:
|
312
|
+
|
313
|
+
- rest_client
|
314
|
+
|
315
|
+
`paginator` has the following methods:
|
316
|
+
|
317
|
+
## paginate
|
318
|
+
|
319
|
+
`paginate` accepts the following parameters:
|
320
|
+
|
321
|
+
- http_method
|
322
|
+
- uri
|
323
|
+
- payload (optional)
|
324
|
+
- headers (optional)
|
325
|
+
- data (optional)
|
326
|
+
|
327
|
+
`paginate` returns:
|
328
|
+
|
329
|
+
- an array where each element is a _Response_ object for each page (ie header and the body), if data is false.
|
330
|
+
- an array where each element is one entity from every `response.body` for each page (ie the data), if data is true.
|
331
|
+
|
332
|
+
## `HeaderLink`
|
333
|
+
|
334
|
+
`new` accepts the following parameters:
|
335
|
+
|
336
|
+
- per_page (optional)
|
337
|
+
|
338
|
+
`new` returns a _HeaderLink_ (_Paginator_) object.
|
339
|
+
|
340
|
+
## `Echo`
|
341
|
+
|
342
|
+
`new` accepts the following parameters:
|
343
|
+
|
344
|
+
- limit (optional)
|
345
|
+
|
346
|
+
`new` returns an _Echo_ (_Paginator_) object.
|
347
|
+
|
348
|
+
<a name="request"></a>
|
349
|
+
# `Request`
|
350
|
+
|
351
|
+
`request` has the following accessors:
|
352
|
+
|
353
|
+
- uri
|
354
|
+
- headers
|
355
|
+
- http_method
|
356
|
+
- payload
|
357
|
+
- query_params
|
358
|
+
- segment_params
|
359
|
+
|
360
|
+
`request` has the following methods:
|
361
|
+
|
362
|
+
## new
|
363
|
+
|
364
|
+
`new` accepts the following parameters:
|
365
|
+
|
366
|
+
- http_method
|
367
|
+
- uri
|
368
|
+
- segment_params (optional)
|
369
|
+
- payload (optional)
|
370
|
+
- query_params (optional)
|
371
|
+
- headers (optional)
|
372
|
+
|
373
|
+
`new` returns a _Request_ object.
|
374
|
+
|
375
|
+
<a name="reponse"></a>
|
376
|
+
# `Response`
|
377
|
+
|
378
|
+
_Response_ objects have the following methods:
|
379
|
+
|
380
|
+
- `code`: The HTTP response code
|
381
|
+
- `body`: The response body will be returned as a hash if the content-type of the response is a string otherwise it will return a string
|
382
|
+
- `headers`: A hash of HTTP response header objects
|
383
|
+
|
384
|
+
## Exceptions
|
385
|
+
|
386
|
+
- `RestClientError`: Exceptions that are raised by the rest-client GEM will be captured in this exception
|
387
|
+
- `RestClientNotSuccessful` : Unsuccessful requests (i.e. a `response` with a status that is not between 200 and 207)
|
388
|
+
- Get server response by calling .response on the exception
|
389
|
+
|
390
|
+
```ruby
|
391
|
+
begin
|
392
|
+
request = Request.new({http_method: :get, uri: "https://www.host.com/public/api/v1/resource" })
|
393
|
+
response = rest_client.execute({ request: request })
|
394
|
+
rescue RestClientError => e
|
395
|
+
e.response
|
396
|
+
end
|
397
|
+
```
|
398
|
+
|
399
|
+
|
400
|
+
---
|
401
|
+
|
402
|
+
<a name="examples"></a>
|
403
|
+
# Examples
|
404
|
+
|
405
|
+
### REST API call
|
406
|
+
|
407
|
+
```ruby
|
408
|
+
host_url = "https://www.host.com"
|
409
|
+
username = "api_user_name"
|
410
|
+
password = "password"
|
411
|
+
client = Client.new({ host: host_url })
|
412
|
+
client.authenticator = Authenticator::Basic.new({ username: username, password: password })
|
413
|
+
client.paginator = Paginator::HeaderLink.new({ per_page: 10 })
|
414
|
+
|
415
|
+
response = client.make_request({ http_method: :get, uri: "/api/v1/resource" })
|
416
|
+
|
417
|
+
# paginated request
|
418
|
+
data = client.make_request_for_pages({ http_method: :get, uri: "/api/v1/resource", data: true })
|
419
|
+
|
420
|
+
```
|
421
|
+
|
422
|
+
### Canvas
|
423
|
+
|
424
|
+
```ruby
|
425
|
+
canvas_host = "https://host.instructure.com"
|
426
|
+
canvas_access_token = "access_token"
|
427
|
+
canvas_client = Client.new({ host: canvas_host })
|
428
|
+
canvas_client.authenticator = Authenticator::Token.new({ access_token: canvas_access_token })
|
429
|
+
canvas_client.paginator = Paginator::HeaderLink.new({ per_page: 10 })
|
430
|
+
|
431
|
+
canvas_response = canvas_client.make_request({ http_method: :get, uri: "/api/v1/accounts/1/terms" })
|
432
|
+
|
433
|
+
# paginated request
|
434
|
+
canvas_data = canvas_client.make_request_for_pages({ http_method: :get, uri: "/api/v1/accounts/1/terms", data: true })
|
435
|
+
```
|
436
|
+
|
437
|
+
### Echo
|
438
|
+
|
439
|
+
```ruby
|
440
|
+
echo_host = "https://echo360.org.au"
|
441
|
+
echo_client_id = "client_id"
|
442
|
+
echo_client_secret = "client_secret"
|
443
|
+
echo_client = Client.new({ host: echo_host })
|
444
|
+
echo_client.authenticator = Authenticator::Oauth.new({ site: echo_host, token_url_path: "/oauth2/access_token", client_id: echo_client_id, client_secret: echo_client_secret })
|
445
|
+
echo_client.paginator = Paginator::Echo.new({ limit: 10 })
|
446
|
+
|
447
|
+
echo_response = echo_client.make_request({ http_method: :get, uri: "/public/api/v1/terms" })
|
448
|
+
echo_data = echo_client.make_request_for_pages({ http_method: :get, uri: "/public/api/v1/terms", data: true })
|
449
|
+
```
|
450
|
+
|
451
|
+
## Create a request object
|
452
|
+
|
453
|
+
Create a `rest_client`.
|
454
|
+
|
455
|
+
```ruby
|
456
|
+
rest_client = RestClientWrapper::RestClient.new({ host: "https://www.host.com" })
|
457
|
+
```
|
458
|
+
|
459
|
+
## Request with a segmented absolute URI
|
460
|
+
|
461
|
+
```ruby
|
462
|
+
request = Request.new({http_method: :get, uri: "https://www.host.com/public/api/v1/users/%<user_id>s" })
|
463
|
+
request.segment_params = { user_id: "user_id" }
|
464
|
+
response = rest_client.execute({ request: request })
|
465
|
+
```
|
466
|
+
|
467
|
+
## Request with a segmented resource path
|
468
|
+
|
469
|
+
```ruby
|
470
|
+
rest_client = RestClientWrapper::RestClient.new({ host: "https://www.host.com" })
|
471
|
+
request = Request.new({ http_method: :get, uri: "/public/api/v1/users/%<user_id>s" })
|
472
|
+
request.segment_params = { user_id: "user_id" }
|
473
|
+
response = rest_client.execute({ request: request })
|
474
|
+
```
|
475
|
+
|
476
|
+
## Query Parameters
|
477
|
+
|
478
|
+
```ruby
|
479
|
+
rest_client = RestClientWrapper::RestClient.new({ host: "https://www.host.com" })
|
480
|
+
request = Request.new({ http_method: :put, uri: "/api/v1/resource/" })
|
481
|
+
request.payload = { user_id: "user_id" }
|
482
|
+
request.query_params = { id: "value" }
|
483
|
+
response = rest_client.execute({ request: request })
|
484
|
+
```
|