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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 61eaaa77dfcbab57b714007844456fe903c759cbb981761a43b7eb4910da3463
4
- data.tar.gz: 10e7bbe8cc3b35887eb34c32562af637ed8cd4aae34df0547c2e2cd52a730a7e
3
+ metadata.gz: 44aa9166918c27766f3d696c23cc78b08e1f956edb6ae8a7413c9e88f01c48e7
4
+ data.tar.gz: 1068bcb89fb8da7af5505177f989997794615703df092d8d27fa55479987565c
5
5
  SHA512:
6
- metadata.gz: 251b2a247480a4f7b3c46a70cd469c3ad24cbdb6c245703ec60658ae3429107a7a364eb12e8794c2e28729ebb58e7a17bc1d2fbeebf59a035d5f277032ba7d82
7
- data.tar.gz: e4fb534d1775963465155761cd4e6b8a7f14e7c66b0f0406d48d39abe4810906c588a9f00fea1b9325b1ed6d1682c9224f47b07c0f75e51b48986d2be43f5e0c
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
@@ -68,9 +68,10 @@ module Flexirest
68
68
  end
69
69
 
70
70
  if cache_store && (headers[:etag] || headers[:expires])
71
- key = "#{request.class_name}:#{request.original_url}"
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 @class_name.nil? # Old cached instance
117
+ return @result if @old_cached_instance
116
118
 
117
119
  if @result.is_a?(Array)
118
120
  ri = ResultIterator.new(self)
@@ -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
- case http_method
611
- when :get
610
+ if http_method == :get && !@method[:options][:send_get_body]
612
611
  response = connection.get(@url, request_options)
613
- when :put
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
- when :post
616
+ elsif http_method == :post
616
617
  response = connection.post(@url, @body, request_options)
617
- when :patch
618
+ elsif http_method == :patch
618
619
  response = connection.patch(@url, @body, request_options)
619
- when :delete
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}")
@@ -1,3 +1,3 @@
1
1
  module Flexirest
2
- VERSION = "1.12.3"
2
+ VERSION = "1.12.5"
3
3
  end
@@ -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)
@@ -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.3
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: 2024-03-21 00:00:00.000000000 Z
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.6
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