flexirest 1.12.3 → 1.12.5
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 +12 -0
- data/docs/basic-usage.md +6 -0
- data/lib/flexirest/caching.rb +6 -4
- data/lib/flexirest/request.rb +10 -9
- data/lib/flexirest/version.rb +1 -1
- data/spec/lib/caching_spec.rb +45 -9
- data/spec/lib/request_spec.rb +6 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 44aa9166918c27766f3d696c23cc78b08e1f956edb6ae8a7413c9e88f01c48e7
|
4
|
+
data.tar.gz: 1068bcb89fb8da7af5505177f989997794615703df092d8d27fa55479987565c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9cddabff55c7531fdb3856c863fc9888fa3731c82135f9a02c4e3d5026514c479815ecaa499fc38b6f50c6579bff7703bcbaef688d76ea067a43f7a26dc8efc5
|
7
|
+
data.tar.gz: 204f29f4a0baa07661ea497d88799f137ed55114fdea808f5a1ea905a21f9ff51f2d0ce1c9a82d985c140c6e6f4fc29ae26e394a34a63cc51b87907dbef81139
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 1.12.5
|
4
|
+
|
5
|
+
Feature:
|
6
|
+
|
7
|
+
- Some broken APIs require a GET body, even though this is against HTTP spec. Added a `send_get_body` parameter like we already have for DELETE requests (thanks to Jan Schroeder for the request)
|
8
|
+
|
9
|
+
## 1.12.4
|
10
|
+
|
11
|
+
Bugfix:
|
12
|
+
|
13
|
+
- 204 responses could not be read from Cache (thanks to rgisiger for the PR)
|
14
|
+
|
3
15
|
## 1.12.3
|
4
16
|
|
5
17
|
Bugfix:
|
data/docs/basic-usage.md
CHANGED
@@ -52,6 +52,12 @@ For `delete` requests whether an API can handle a body or not is undefined. The
|
|
52
52
|
delete :remove, "/people/:id", send_delete_body: true
|
53
53
|
```
|
54
54
|
|
55
|
+
In a similar way, although it's against the HTTP specification, you can force a GET request to send a request body if your API requires that:
|
56
|
+
|
57
|
+
```
|
58
|
+
get :people_search, "/people/search", send_get_body: true
|
59
|
+
```
|
60
|
+
|
55
61
|
If an API returns an array of results and you have [will_paginate](https://rubygems.org/gems/will_paginate) installed then you can call the paginate method to return a particular page of the results (note: this doesn't reduce the load on the server, but it can help with pagination if you have a cached response).
|
56
62
|
|
57
63
|
```ruby
|
data/lib/flexirest/caching.rb
CHANGED
@@ -68,9 +68,10 @@ module Flexirest
|
|
68
68
|
end
|
69
69
|
|
70
70
|
if cache_store && (headers[:etag] || headers[:expires])
|
71
|
-
|
71
|
+
class_name = request.class_name
|
72
|
+
key = "#{class_name}:#{request.original_url}"
|
72
73
|
Flexirest::Logger.debug " \033[1;4;32m#{Flexirest.name}\033[0m #{key} - Writing to cache" unless quiet
|
73
|
-
cached_response = CachedResponse.new(status:response.status, result:result, response_headers: headers)
|
74
|
+
cached_response = CachedResponse.new(status:response.status, result:result, response_headers: headers, class_name:class_name)
|
74
75
|
cached_response.etag = "#{headers[:etag]}" if headers[:etag]
|
75
76
|
cached_response.expires = Time.parse(headers[:expires]) rescue nil if headers[:expires]
|
76
77
|
if cached_response.etag.present? || cached_response.expires
|
@@ -101,18 +102,19 @@ module Flexirest
|
|
101
102
|
@etag = options[:etag]
|
102
103
|
@expires = options[:expires]
|
103
104
|
@response_headers = options[:response_headers]
|
105
|
+
@old_cached_instance = options[:result].class.name.nil?
|
104
106
|
|
105
|
-
@class_name = options[:result].class.name
|
106
107
|
if options[:result].is_a?(ResultIterator)
|
107
108
|
@class_name = options[:result][0].class.name
|
108
109
|
@result = options[:result].map{|i| {}.merge(i._attributes)}
|
109
110
|
else
|
111
|
+
@class_name = options[:class_name]
|
110
112
|
@result = {}.merge(options[:result].try(:_attributes) || {})
|
111
113
|
end
|
112
114
|
end
|
113
115
|
|
114
116
|
def result
|
115
|
-
return @result if @
|
117
|
+
return @result if @old_cached_instance
|
116
118
|
|
117
119
|
if @result.is_a?(Array)
|
118
120
|
ri = ResultIterator.new(self)
|
data/lib/flexirest/request.rb
CHANGED
@@ -361,10 +361,10 @@ module Flexirest
|
|
361
361
|
if @explicit_parameters
|
362
362
|
params = @explicit_parameters
|
363
363
|
end
|
364
|
-
if http_method == :get || (http_method == :delete && !@method[:options][:send_delete_body] && proxy != :json_api)
|
364
|
+
if (http_method == :get && !@method[:options][:send_get_body]) || (http_method == :delete && !@method[:options][:send_delete_body] && proxy != :json_api)
|
365
365
|
@get_params = default_params.merge(params || {})
|
366
366
|
@post_params = nil
|
367
|
-
elsif http_method == :delete && @method[:options][:send_delete_body]
|
367
|
+
elsif (http_method == :get && @method[:options][:send_get_body]) || (http_method == :delete && @method[:options][:send_delete_body])
|
368
368
|
@post_params = default_params.merge(params || {})
|
369
369
|
@get_params = {}
|
370
370
|
elsif params.is_a? String
|
@@ -476,7 +476,7 @@ module Flexirest
|
|
476
476
|
|
477
477
|
headers["Accept"] ||= "application/vnd.api+json"
|
478
478
|
JsonAPIProxy::Headers.save(headers)
|
479
|
-
elsif http_method == :get || (http_method == :delete && !@method[:options][:send_delete_body])
|
479
|
+
elsif (http_method == :get && !@method[:options][:send_get_body]) || (http_method == :delete && !@method[:options][:send_delete_body])
|
480
480
|
if request_body_type == :form_encoded
|
481
481
|
headers["Content-Type"] ||= "application/x-www-form-urlencoded; charset=utf-8"
|
482
482
|
elsif request_body_type == :form_multipart
|
@@ -607,16 +607,17 @@ module Flexirest
|
|
607
607
|
request_options[:timeout] = @method[:options][:timeout]
|
608
608
|
end
|
609
609
|
|
610
|
-
|
611
|
-
when :get
|
610
|
+
if http_method == :get && !@method[:options][:send_get_body]
|
612
611
|
response = connection.get(@url, request_options)
|
613
|
-
|
612
|
+
elsif http_method == :get
|
613
|
+
response = connection.get(@url, @body, request_options)
|
614
|
+
elsif http_method == :put
|
614
615
|
response = connection.put(@url, @body, request_options)
|
615
|
-
|
616
|
+
elsif http_method == :post
|
616
617
|
response = connection.post(@url, @body, request_options)
|
617
|
-
|
618
|
+
elsif http_method == :patch
|
618
619
|
response = connection.patch(@url, @body, request_options)
|
619
|
-
|
620
|
+
elsif http_method == :delete
|
620
621
|
response = connection.delete(@url, @body, request_options)
|
621
622
|
else
|
622
623
|
raise InvalidRequestException.new("Invalid method #{http_method}")
|
data/lib/flexirest/version.rb
CHANGED
data/spec/lib/caching_spec.rb
CHANGED
@@ -109,6 +109,7 @@ describe Flexirest::Caching do
|
|
109
109
|
base_url "http://www.example.com"
|
110
110
|
get :all, "/"
|
111
111
|
put :save_all, "/"
|
112
|
+
get :plain, "/plain/:id", plain: true
|
112
113
|
end
|
113
114
|
|
114
115
|
Person.cache_store = CachingExampleCacheStore5.new({ expires_in: 1.day.to_i }) # default cache expiration
|
@@ -121,7 +122,8 @@ describe Flexirest::Caching do
|
|
121
122
|
cached_response = Flexirest::CachedResponse.new(
|
122
123
|
status:200,
|
123
124
|
result:@cached_object,
|
124
|
-
etag:@etag
|
125
|
+
etag:@etag,
|
126
|
+
class_name:Person.name)
|
125
127
|
expect_any_instance_of(CachingExampleCacheStore5).to receive(:read).once.with("Person:/").and_return(Marshal.dump(cached_response))
|
126
128
|
expect_any_instance_of(Flexirest::Connection).to receive(:get){ |connection, path, options|
|
127
129
|
expect(path).to eq('/')
|
@@ -131,11 +133,23 @@ describe Flexirest::Caching do
|
|
131
133
|
expect(ret.first_name).to eq("Johnny")
|
132
134
|
end
|
133
135
|
|
136
|
+
it "should read the response to the cache store if response is a 204 with empty bodies and cache is wanted" do
|
137
|
+
cached_response = Flexirest::CachedResponse.new(
|
138
|
+
status:204,
|
139
|
+
result:true,
|
140
|
+
expires:Time.now + 30,
|
141
|
+
class_name:Person.name)
|
142
|
+
expect_any_instance_of(CachingExampleCacheStore5).to receive(:read).once.with("Person:/").and_return(Marshal.dump(cached_response))
|
143
|
+
expect_any_instance_of(Flexirest::Connection).not_to receive(:get)
|
144
|
+
Person.all
|
145
|
+
end
|
146
|
+
|
134
147
|
it "should not read from the cache store to check for an etag unless it's a GET request" do
|
135
148
|
cached_response = Flexirest::CachedResponse.new(
|
136
149
|
status:200,
|
137
150
|
result:@cached_object,
|
138
|
-
etag:@etag
|
151
|
+
etag:@etag,
|
152
|
+
class_name:Person.name)
|
139
153
|
expect_any_instance_of(CachingExampleCacheStore5).to_not receive(:read)
|
140
154
|
expect_any_instance_of(Flexirest::Connection).to receive(:put).and_return(::FaradayResponseMock.new(OpenStruct.new(status:200, body: {result: "foo"}.to_json, response_headers:{})))
|
141
155
|
ret = Person.save_all
|
@@ -145,7 +159,8 @@ describe Flexirest::Caching do
|
|
145
159
|
cached_response = Flexirest::CachedResponse.new(
|
146
160
|
status: 200,
|
147
161
|
result: @cached_object,
|
148
|
-
etag: @etag
|
162
|
+
etag: @etag,
|
163
|
+
class_name:Person.name
|
149
164
|
)
|
150
165
|
allow_any_instance_of(CachingExampleCacheStore5).to receive(:read).and_return(Marshal.dump(cached_response))
|
151
166
|
new_name = 'Pete'
|
@@ -166,7 +181,8 @@ describe Flexirest::Caching do
|
|
166
181
|
cached_response = Flexirest::CachedResponse.new(
|
167
182
|
status:200,
|
168
183
|
result:@cached_object,
|
169
|
-
expires:Time.now + 30
|
184
|
+
expires:Time.now + 30,
|
185
|
+
class_name:Person.name)
|
170
186
|
expect_any_instance_of(CachingExampleCacheStore5).to receive(:read).once.with("Person:/").and_return(Marshal.dump(cached_response))
|
171
187
|
expect_any_instance_of(Flexirest::Connection).not_to receive(:get)
|
172
188
|
ret = Person.all
|
@@ -177,7 +193,8 @@ describe Flexirest::Caching do
|
|
177
193
|
cached_response = Flexirest::CachedResponse.new(
|
178
194
|
status:200,
|
179
195
|
result:@cached_object,
|
180
|
-
expires:Time.now + 30
|
196
|
+
expires:Time.now + 30,
|
197
|
+
class_name:Person.name)
|
181
198
|
Timecop.travel(Time.now + 60)
|
182
199
|
expect_any_instance_of(CachingExampleCacheStore5).to receive(:read).once.with("Person:/").and_return(nil)
|
183
200
|
expect_any_instance_of(Flexirest::Connection).to receive(:get).with("/", an_instance_of(Hash)).and_return(::FaradayResponseMock.new(OpenStruct.new(status:200, body:"{\"result\":true}", response_headers:{})))
|
@@ -189,7 +206,8 @@ describe Flexirest::Caching do
|
|
189
206
|
cached_response = Flexirest::CachedResponse.new(
|
190
207
|
status:200,
|
191
208
|
result:@cached_object,
|
192
|
-
expires:Time.now + 30
|
209
|
+
expires:Time.now + 30,
|
210
|
+
class_name:Person.name)
|
193
211
|
expect_any_instance_of(CachingExampleCacheStore5).to receive(:read).once.with("Person:/").and_return(Marshal.dump(cached_response))
|
194
212
|
expect_any_instance_of(Flexirest::Connection).not_to receive(:get)
|
195
213
|
ret = Person.all
|
@@ -201,7 +219,8 @@ describe Flexirest::Caching do
|
|
201
219
|
cached_response = Flexirest::CachedResponse.new(
|
202
220
|
status:200,
|
203
221
|
result:@cached_object,
|
204
|
-
expires:Time.now + 30
|
222
|
+
expires:Time.now + 30,
|
223
|
+
class_name:Person.name)
|
205
224
|
expect_any_instance_of(CachingExampleCacheStore5).to receive(:read).once.with("Person:/").and_return(Marshal.dump(cached_response))
|
206
225
|
expect_any_instance_of(Flexirest::Connection).not_to receive(:get)
|
207
226
|
p = Person.new(first_name:"Billy")
|
@@ -219,7 +238,8 @@ describe Flexirest::Caching do
|
|
219
238
|
status:200,
|
220
239
|
result:object,
|
221
240
|
etag:etag,
|
222
|
-
expires:Time.now + 30
|
241
|
+
expires:Time.now + 30,
|
242
|
+
class_name:Person.name)
|
223
243
|
expect_any_instance_of(CachingExampleCacheStore5).to receive(:read).once.with("Person:/").and_return(Marshal.dump(cached_response))
|
224
244
|
expect_any_instance_of(Flexirest::Connection).not_to receive(:get)
|
225
245
|
ret = Person.all
|
@@ -237,7 +257,8 @@ describe Flexirest::Caching do
|
|
237
257
|
status:200,
|
238
258
|
result:object,
|
239
259
|
etag:etag,
|
240
|
-
expires:Time.now + 30
|
260
|
+
expires:Time.now + 30,
|
261
|
+
class_name:Person.name)
|
241
262
|
Timecop.travel(Time.now + 60)
|
242
263
|
expect_any_instance_of(CachingExampleCacheStore5).to receive(:read).once.with("Person:/").and_return(nil)
|
243
264
|
expect_any_instance_of(Flexirest::Connection).to receive(:get).with("/", an_instance_of(Hash)).and_return(::FaradayResponseMock.new(OpenStruct.new(status:200, body:"[{\"first_name\":\"Billy\"}]", response_headers:{})))
|
@@ -247,6 +268,21 @@ describe Flexirest::Caching do
|
|
247
268
|
Timecop.return
|
248
269
|
end
|
249
270
|
|
271
|
+
it "should not write the response to the cache if it is a plain request" do
|
272
|
+
response_body = "This is another non-JSON string"
|
273
|
+
expect_any_instance_of(CachingExampleCacheStore5).to receive(:read).once.with("Person:/plain/1234").and_return(nil)
|
274
|
+
expect_any_instance_of(CachingExampleCacheStore5).to receive(:write).once.with("Person:/plain/1234", an_instance_of(String), hash_excluding(:etag))
|
275
|
+
expect_any_instance_of(Flexirest::Connection).to receive(:get).with(any_args).and_return(::FaradayResponseMock.new(OpenStruct.new(status:200, response_headers:{expires:(Time.now + 30).rfc822}, body:response_body)))
|
276
|
+
Person.plain(id:1234)
|
277
|
+
end
|
278
|
+
|
279
|
+
it "should write the response to the cache if response is a 204 with empty bodies and with expires set (or an etag)" do
|
280
|
+
expect_any_instance_of(CachingExampleCacheStore5).to receive(:read).once.with("Person:/").and_return(nil)
|
281
|
+
expect_any_instance_of(CachingExampleCacheStore5).to receive(:write).once.with("Person:/", an_instance_of(String), hash_excluding(:etag))
|
282
|
+
expect_any_instance_of(Flexirest::Connection).to receive(:get).with(any_args).and_return(::FaradayResponseMock.new(OpenStruct.new(status:204, response_headers:{expires:(Time.now + 30).rfc822}, body: nil)))
|
283
|
+
Person.all
|
284
|
+
end
|
285
|
+
|
250
286
|
it "should not write the response to the cache unless it has caching headers" do
|
251
287
|
expect_any_instance_of(CachingExampleCacheStore5).to receive(:read).once.with("Person:/").and_return(nil)
|
252
288
|
expect_any_instance_of(CachingExampleCacheStore5).not_to receive(:write)
|
data/spec/lib/request_spec.rb
CHANGED
@@ -54,6 +54,7 @@ describe Flexirest::Request do
|
|
54
54
|
put :conversion_child, "/put/:id", parse_fields: [:converted_child]
|
55
55
|
delete :remove, "/remove/:id"
|
56
56
|
delete :remove_body, "/remove/:id", send_delete_body: true
|
57
|
+
get :get_body, "/get-body", send_get_body: true
|
57
58
|
get :hal, "/hal", fake:"{\"_links\":{\"child\": {\"href\": \"/child/1\"}, \"other\": {\"href\": \"/other/1\"}, \"cars\":[{\"href\": \"/car/1\", \"name\":\"car1\"}, {\"href\": \"/car/2\", \"name\":\"car2\"}, {\"href\": \"/car/not-embed\", \"name\":\"car_not_embed\"} ], \"lazy\": {\"href\": \"/lazy/load\"}, \"invalid\": [{\"href\": \"/invalid/1\"}]}, \"_embedded\":{\"other\":{\"name\":\"Jane\"},\"child\":{\"name\":\"Billy\"}, \"cars\":[{\"_links\": {\"self\": {\"href\": \"/car/1\"} }, \"make\": \"Bugatti\", \"model\": \"Veyron\"}, {\"_links\": {\"self\": {\"href\": \"/car/2\"} }, \"make\": \"Ferrari\", \"model\": \"F458 Italia\"} ], \"invalid\": [{\"present\":true, \"_links\": {} } ] } }", has_many:{other:ExampleOtherClient}
|
58
59
|
get :fake_object, "/fake", fake:"{\"result\":true, \"list\":[1,2,3,{\"test\":true}], \"child\":{\"grandchild\":{\"test\":true}}}"
|
59
60
|
get :fake_proc_object, "/fake", fake:->(request) { "{\"result\":#{request.get_params[:id]}}" }
|
@@ -451,6 +452,11 @@ describe Flexirest::Request do
|
|
451
452
|
ExampleClient.all
|
452
453
|
end
|
453
454
|
|
455
|
+
it "should get an HTTP connection when called and call get with a body if send_get_body is specified" do
|
456
|
+
expect_any_instance_of(Flexirest::Connection).to receive(:get).with("/get-body", "something=else", an_instance_of(Hash)).and_return(::FaradayResponseMock.new(OpenStruct.new(body:'{"result":true}', response_headers:{})))
|
457
|
+
ExampleClient.get_body(something: "else")
|
458
|
+
end
|
459
|
+
|
454
460
|
it "should get an HTTP connection when called and call delete on it" do
|
455
461
|
expect_any_instance_of(Flexirest::Connection).to receive(:delete).with("/remove/1", "", an_instance_of(Hash)).and_return(::FaradayResponseMock.new(OpenStruct.new(body:'{"result":true}', response_headers:{})))
|
456
462
|
ExampleClient.remove(id:1)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flexirest
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.12.
|
4
|
+
version: 1.12.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andy Jeffries
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-02-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -407,7 +407,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
407
407
|
- !ruby/object:Gem::Version
|
408
408
|
version: '0'
|
409
409
|
requirements: []
|
410
|
-
rubygems_version: 3.5.
|
410
|
+
rubygems_version: 3.5.21
|
411
411
|
signing_key:
|
412
412
|
specification_version: 4
|
413
413
|
summary: This gem is for accessing REST services in a flexible way. ActiveResource
|