wrest 2.1.9 → 4.0.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 +5 -5
- data/CHANGELOG +6 -0
- data/LICENCE +1 -1
- data/README.md +47 -40
- data/bin/wrest +2 -1
- data/bin/wrest_shell.rb +10 -8
- data/lib/wrest/async_request/event_machine_backend.rb +3 -1
- data/lib/wrest/async_request/thread_backend.rb +5 -2
- data/lib/wrest/async_request/thread_pool.rb +4 -2
- data/lib/wrest/async_request.rb +7 -6
- data/lib/wrest/cache_proxy.rb +39 -28
- data/lib/wrest/caching/memcached.rb +21 -18
- data/lib/wrest/caching/redis.rb +22 -22
- data/lib/wrest/caching.rb +16 -14
- data/lib/wrest/callback.rb +19 -16
- data/lib/wrest/components/container/alias_accessors.rb +51 -47
- data/lib/wrest/components/container/typecaster.rb +146 -95
- data/lib/wrest/components/container.rb +171 -152
- data/lib/wrest/components/mutators/base.rb +43 -34
- data/lib/wrest/components/mutators/camel_to_snake_case.rb +7 -3
- data/lib/wrest/components/mutators/{xml_mini_type_caster.rb → xml_type_caster.rb} +29 -16
- data/lib/wrest/components/mutators.rb +21 -19
- data/lib/wrest/components/translators/content_types.rb +20 -16
- data/lib/wrest/components/translators/json.rb +19 -16
- data/lib/wrest/components/translators/txt.rb +19 -15
- data/lib/wrest/components/translators/xml/conversions.rb +56 -0
- data/lib/wrest/components/translators/xml.rb +60 -18
- data/lib/wrest/components/translators.rb +7 -6
- data/lib/wrest/components.rb +11 -8
- data/lib/wrest/core_ext/hash/conversions.rb +10 -10
- data/lib/wrest/core_ext/hash.rb +4 -2
- data/lib/wrest/core_ext/string/conversions.rb +14 -13
- data/lib/wrest/core_ext/string.rb +5 -3
- data/lib/wrest/exceptions.rb +4 -2
- data/lib/wrest/hash_with_case_insensitive_access.rb +8 -8
- data/lib/wrest/hash_with_indifferent_access.rb +442 -0
- data/lib/wrest/http_codes.rb +20 -19
- data/lib/wrest/http_shared/headers.rb +2 -0
- data/lib/wrest/http_shared/standard_headers.rb +2 -2
- data/lib/wrest/http_shared/standard_tokens.rb +8 -6
- data/lib/wrest/http_shared.rb +5 -3
- data/lib/wrest/multipart.rb +20 -11
- data/lib/wrest/native/connection_factory.rb +15 -11
- data/lib/wrest/native/delete.rb +15 -11
- data/lib/wrest/native/get.rb +60 -55
- data/lib/wrest/native/options.rb +15 -11
- data/lib/wrest/native/patch.rb +27 -0
- data/lib/wrest/native/post.rb +15 -11
- data/lib/wrest/native/post_multipart.rb +22 -18
- data/lib/wrest/native/put.rb +16 -12
- data/lib/wrest/native/put_multipart.rb +22 -18
- data/lib/wrest/native/redirection.rb +13 -12
- data/lib/wrest/native/request.rb +144 -106
- data/lib/wrest/native/response.rb +87 -78
- data/lib/wrest/native/session.rb +49 -40
- data/lib/wrest/native.rb +14 -11
- data/lib/wrest/test/request_patches.rb +10 -3
- data/lib/wrest/test.rb +3 -1
- data/lib/wrest/uri/builders.rb +14 -12
- data/lib/wrest/uri.rb +92 -50
- data/lib/wrest/uri_template.rb +11 -7
- data/lib/wrest/utils.rb +129 -0
- data/lib/wrest/version.rb +3 -1
- data/lib/wrest.rb +31 -33
- data/lib/wrest_no_ext.rb +2 -0
- metadata +91 -56
- data/lib/wrest/components/mutators/xml_simple_type_caster.rb +0 -37
- data/lib/wrest/xml_mini/jdom/xpath_filter.rb +0 -17
- data/lib/wrest/xml_mini/jdom.rb +0 -6
- data/lib/wrest/xml_mini/libxml/xpath_filter.rb +0 -12
- data/lib/wrest/xml_mini/libxml.rb +0 -8
- data/lib/wrest/xml_mini/nokogiri/xpath_filter.rb +0 -15
- data/lib/wrest/xml_mini/nokogiri.rb +0 -7
- data/lib/wrest/xml_mini/rexml/xpath_filter.rb +0 -15
- data/lib/wrest/xml_mini/rexml.rb +0 -8
- data/lib/wrest/xml_mini.rb +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 07fc2ba6c267b466a0caa4366cb63e1657b5966a4140742ed386c6fd657df03f
|
4
|
+
data.tar.gz: f917474be39d0ab7d89a4ba5e652e76798bb51619339dff36ffb0e7453f9b118
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 783b115e74659773e4a04de550d713c30a906ecd2e3de517d168d5535a588366164d440fd47782e975d3236aee8d0a66fe37e729f25440ee67592526ee4c89d7
|
7
|
+
data.tar.gz: 7b2ed5a8a9638cc5ead4ac39edbb27a54ac03e5a9da97ec627eaa0e322979ba4ffcf1e3e52bfc2ffe61055d6d2f788d445c242954969971a052989e3eeeecf1e
|
data/CHANGELOG
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
Features under the section marked 'Current' are completed but pending release as a gem. If you need any of these, you'll need to use the latest source from the git repository.
|
2
2
|
|
3
|
+
== Current
|
4
|
+
* Upgrade gems and fix build on Ruby 3.1.2
|
5
|
+
|
3
6
|
Features under a numbered section are complete and available in the Wrest gem.
|
4
7
|
|
8
|
+
== 2.2.0
|
9
|
+
* Add support for HTTP PATCH [Aditi Raveesh]
|
10
|
+
|
5
11
|
== 2.1.9
|
6
12
|
* Switch to using concurrent-ruby
|
7
13
|
|
data/LICENCE
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright 2009 -
|
1
|
+
Copyright 2009 - 2022 Sidu Ponnappa
|
2
2
|
Licensed under the Apache License, Version 2.0 (the "License");
|
3
3
|
you may not use this file except in compliance with the License.
|
4
4
|
You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
data/README.md
CHANGED
@@ -1,25 +1,36 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
1
|
+
# Wrest 4.0.0.dev
|
2
|
+
|
3
|
+
<p align="center"><img src="docs/wrest-logo-320x320.png" width="320"></p>
|
4
|
+
<p align="center">
|
5
|
+
<a href="https://rubygems.org/gems/wrest">
|
6
|
+
<img src="https://badge.fury.io/rb/wrest.svg" alt="Gem Version" height="18">
|
7
|
+
</a>
|
8
|
+
<a href="https://github.com/kaiwren/wrest/actions/workflows/ruby.yml">
|
9
|
+
<img src="https://github.com/kaiwren/wrest/actions/workflows/ruby.yml/badge.svg" alt="Ruby" style="max-width: 100%;">
|
10
|
+
</a>
|
11
|
+
<a href="https://github.com/kaiwren/wrest/actions/workflows/jruby.yml">
|
12
|
+
<img src="https://github.com/kaiwren/wrest/actions/workflows/jruby.yml/badge.svg" alt="JRuby" style="max-width: 100%;">
|
13
|
+
</a>
|
14
|
+
<a href="https://codeclimate.com/github/kaiwren/wrest/maintainability">
|
15
|
+
<img src="https://api.codeclimate.com/v1/badges/dc0366a60000561951ab/maintainability" />
|
16
|
+
</a>
|
17
|
+
</p>
|
18
|
+
|
19
|
+
|
20
|
+
Wrest is a ruby REST/HTTP client library. It is currently in use at 10x🦄 scale across all Ruby/JRuby systems at [Gojek](https://twitter.com/GojekTech).
|
21
|
+
|
22
|
+
* Quick tool to wrangle APIs to powerful library to build complex production grade systems, Wrest does it all
|
23
|
+
* Clean, object-oriented API with URLs as first class entities
|
11
24
|
* Supports RFC 2616 based [caching](https://github.com/kaiwren/wrest/blob/caching/Caching.markdown)
|
12
|
-
* Async http calls using Threads (
|
13
|
-
* Allows you to quickly build object oriented wrappers around any web service
|
14
|
-
* Is designed to be used as a library, not just a command line REST client (fewer class/static methods, more object oriented)
|
25
|
+
* Async http calls using Threads (truly useful only on JRuby due to [GIL](https://en.wikipedia.org/wiki/Global_interpreter_lock) limitations on CRuby) or EventMachine
|
15
26
|
* Is spec driven, strongly favours immutable objects and avoids class methods and setters making it better suited for use as a library, especially in multi-threaded environments
|
16
27
|
* Provides convenient HTTP wrappers, redirect handling, serialisation, deserialisation and xpath based lookup
|
17
28
|
|
18
|
-
|
29
|
+
Wrest is currently undergoing a substantial clean-up of syntax and dendencies to bring it up to speed on Ruby 3.x and JRuby 9.3.x. This will be released shortly as version 4.0.0.
|
19
30
|
|
20
|
-
##Examples
|
31
|
+
## Examples
|
21
32
|
|
22
|
-
For Facebook, Twitter, Delicious, GitHub and other API examples, see http://github.com/
|
33
|
+
For Facebook, Twitter, Delicious, GitHub and other API examples, see http://github.com/kaiwren/wrest/tree/master/examples
|
23
34
|
|
24
35
|
### Basic Http Calls
|
25
36
|
|
@@ -28,16 +39,16 @@ For Facebook, Twitter, Delicious, GitHub and other API examples, see http://gith
|
|
28
39
|
* Basic API calls
|
29
40
|
|
30
41
|
```
|
31
|
-
# Works with json and xml out of the box
|
42
|
+
# Works with json and xml out of the box to give you a hash
|
32
43
|
# See lib/wrest/components/translators to add other formats
|
33
44
|
|
34
|
-
'https://api.github.com/repos/
|
45
|
+
'https://api.github.com/repos/rails/rails/issues'.to_uri.get.deserialize
|
35
46
|
```
|
36
47
|
|
37
48
|
* Timeout support
|
38
49
|
|
39
50
|
```
|
40
|
-
'https://api.github.com/repos/c42/wrest/issues'.to_uri
|
51
|
+
'https://api.github.com/repos/c42/wrest/issues'.to_uri(timeout: 5).get.body
|
41
52
|
```
|
42
53
|
|
43
54
|
* Redirect support
|
@@ -53,8 +64,6 @@ For Facebook, Twitter, Delicious, GitHub and other API examples, see http://gith
|
|
53
64
|
* Deserialise with XPath filtering
|
54
65
|
|
55
66
|
```
|
56
|
-
ActiveSupport::XmlMini.backend = 'REXML'
|
57
|
-
|
58
67
|
'http://twitter.com/statuses/public_timeline.xml'.to_uri.get.deserialise(
|
59
68
|
xpath: '//user/name/text()'
|
60
69
|
)
|
@@ -137,7 +146,7 @@ Wrest supports caching with the following pluggable back-ends:
|
|
137
146
|
- Memcached
|
138
147
|
- Redis
|
139
148
|
|
140
|
-
####Hash
|
149
|
+
#### Hash
|
141
150
|
|
142
151
|
Use the following method to enable caching for all requests, and set Hash as the default cache store.
|
143
152
|
Note: Hash should NEVER be used in a production environment. It is unbounded and will keep increasing in size.
|
@@ -153,7 +162,7 @@ To use Hash as a cache store in an explicit request (without setting hash as def
|
|
153
162
|
r1 = "http://c42.in".to_uri.using_hash.get
|
154
163
|
```
|
155
164
|
|
156
|
-
####Memcached
|
165
|
+
#### Memcached
|
157
166
|
|
158
167
|
A Memcached based caching back-end is available in Wrest. You can get instructions on how to install Memcached on your system [here](http://code.google.com/p/memcached/wiki/NewInstallFromPackage).
|
159
168
|
The Dalli gem is used by Wrest to interface with Memcached. Install dalli using 'gem install dalli'.
|
@@ -171,7 +180,7 @@ To use Memcached as a cache store in an explicit request (without setting memcac
|
|
171
180
|
r2 = "http://c42.in".to_uri.using_memcached.get
|
172
181
|
```
|
173
182
|
|
174
|
-
####Redis
|
183
|
+
#### Redis
|
175
184
|
|
176
185
|
Wrest also supports a Redis based caching back-end. Follow the guide [here](http://redis.io/topics/quickstart) to install Redis in your system.
|
177
186
|
It uses [redis-rd](https://github.com/redis/redis-rb) to interface with Redis. Install redis-rb using `gem install redis`.
|
@@ -352,17 +361,6 @@ Detailed http debug logging can be turned on like so (DO NOT USE IN PRODUCTION!
|
|
352
361
|
'https://api.github.com/repos/c42/wrest/issues'.to_uri(detailed_http_logging: $stdout).get.deserialize
|
353
362
|
```
|
354
363
|
|
355
|
-
|
356
|
-
### Json Backend
|
357
|
-
|
358
|
-
Wrest uses the multi_json gem to manage Json backends, allowing it to play nice with Rails 3.1. To change the backend used, you can do the following:
|
359
|
-
|
360
|
-
```
|
361
|
-
MultiJson.engine = :json_gem
|
362
|
-
```
|
363
|
-
|
364
|
-
For more information, look up the [multi_json](http://github.com/intridea/multi_json) documentation.
|
365
|
-
|
366
364
|
### Build
|
367
365
|
|
368
366
|
Standard options are available and can be listed using `rake -T`. Use rake:rcov for coverage and rake:rdoc to generate documentation. The link to the continuous integration build is over at the C42 Engineering [open source](http://c42.in/open_source) page.
|
@@ -396,24 +394,31 @@ You can launch the interactive Wrest shell by running bin/wrest if you have the
|
|
396
394
|
|
397
395
|
Start the Sinatra test server for functional test. The dependencies for the test app are managed separately by a Gemfile under spec/sample_app.
|
398
396
|
|
397
|
+
To start the sample application:
|
398
|
+
|
399
399
|
```
|
400
|
-
|
400
|
+
cd spec/sample_app
|
401
|
+
bundle install
|
402
|
+
bundle exec rake # runs sample app on port 3000
|
401
403
|
```
|
402
404
|
|
403
|
-
Start a memcached daemon/process on port 11211
|
405
|
+
Start a memcached daemon/process on port 11211 and redis on 6379 (both default ports)
|
404
406
|
|
405
407
|
```
|
406
|
-
|
408
|
+
brew install memcached
|
409
|
+
brew install redis
|
410
|
+
brew services start memcached
|
411
|
+
brew services start redis
|
407
412
|
```
|
408
413
|
|
409
414
|
Run the tests in a different terminal:
|
410
415
|
|
411
416
|
```
|
412
417
|
# Run the normal test suite.
|
413
|
-
rake
|
418
|
+
bundle exec rake
|
414
419
|
|
415
420
|
# Runs the functional test suite.
|
416
|
-
rake rspec:functional
|
421
|
+
bundle exec rake rspec:functional
|
417
422
|
```
|
418
423
|
|
419
424
|
## Contributors
|
@@ -427,3 +432,5 @@ Run the tests in a different terminal:
|
|
427
432
|
* Jacques Crocker : [railsjedi](http://github.com/railsjedi)
|
428
433
|
* Jasim A Basheer: [jasim](http://github.com/jasim)
|
429
434
|
* Arvind Laxminarayan: [ardsrk](http://github.com/ardsrk)
|
435
|
+
|
436
|
+
©️ Copyright 2009-2022 [Sidu Ponnappa](http://twitter.com/ponnappa). All Rights Reserved.
|
data/bin/wrest
CHANGED
data/bin/wrest_shell.rb
CHANGED
@@ -1,21 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
puts "Ruby #{RUBY_VERSION}, #{RUBY_RELEASE_DATE}, #{RUBY_PLATFORM}"
|
2
4
|
|
3
|
-
entry_point = File.
|
4
|
-
|
5
|
+
entry_point = File.join(__dir__, '..', 'lib', 'wrest.rb')
|
6
|
+
version_file = File.expand_path(File.join(__dir__, '..', 'lib', 'wrest', 'version.rb'))
|
5
7
|
|
6
8
|
irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
|
7
9
|
|
8
10
|
require 'optparse'
|
9
|
-
options = { :
|
11
|
+
options = { irb: irb }
|
10
12
|
OptionParser.new do |opt|
|
11
|
-
opt.banner =
|
13
|
+
opt.banner = 'Usage: console [options]'
|
12
14
|
opt.on("--irb=[#{irb}]", 'Invoke a different irb.') { |v| options[:irb] = v }
|
13
15
|
opt.parse!(ARGV)
|
14
16
|
end
|
15
17
|
|
16
|
-
libs =
|
17
|
-
|
18
|
+
libs = ' -r irb/completion ' \
|
19
|
+
"-r #{entry_point}"
|
18
20
|
|
19
|
-
require
|
21
|
+
require version_file
|
20
22
|
puts "Loading Wrest #{Wrest::VERSION}"
|
21
|
-
exec "#{options[:irb]} #{libs} --simple-prompt"
|
23
|
+
exec "#{options[:irb]} #{libs} --simple-prompt"
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Copyright 2009 Sidu Ponnappa
|
2
4
|
|
3
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -10,7 +12,7 @@
|
|
10
12
|
begin
|
11
13
|
gem 'eventmachine'
|
12
14
|
rescue Gem::LoadError => e
|
13
|
-
Wrest.logger.debug
|
15
|
+
Wrest.logger.debug 'Eventmachine ~> 0.12.10 not found. Wrest uses Eventmachine to perform evented asynchronous requests'
|
14
16
|
raise e
|
15
17
|
end
|
16
18
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Copyright 2009 Sidu Ponnappa
|
2
4
|
|
3
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -13,14 +15,15 @@ module Wrest
|
|
13
15
|
# Only recommended for production use on JRuby.
|
14
16
|
class ThreadBackend
|
15
17
|
attr_reader :thread_pool
|
18
|
+
|
16
19
|
def initialize(number_of_threads = 5)
|
17
20
|
@thread_pool = ThreadPool.new(number_of_threads)
|
18
21
|
end
|
19
|
-
|
22
|
+
|
20
23
|
def execute(request)
|
21
24
|
@thread_pool.execute_eventually(request)
|
22
25
|
end
|
23
|
-
|
26
|
+
|
24
27
|
# Uses Thread#join to wait until all
|
25
28
|
# background requests are completed.
|
26
29
|
def wait_for_thread_pool!
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Copyright 2009-2016 Sidu Ponnappa
|
2
4
|
|
3
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -13,12 +15,12 @@ module Wrest
|
|
13
15
|
def initialize(number_of_threads)
|
14
16
|
@pool = Concurrent::FixedThreadPool.new(number_of_threads)
|
15
17
|
end
|
16
|
-
|
18
|
+
|
17
19
|
def execute_eventually(request)
|
18
20
|
@pool.post { request.invoke }
|
19
21
|
nil
|
20
22
|
end
|
21
|
-
|
23
|
+
|
22
24
|
def join_pool_threads!
|
23
25
|
@pool.wait_for_termination
|
24
26
|
end
|
data/lib/wrest/async_request.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Copyright 2009 Sidu Ponnappa
|
2
4
|
|
3
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -7,12 +9,11 @@
|
|
7
9
|
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
8
10
|
# See the License for the specific language governing permissions and limitations under the License.
|
9
11
|
|
10
|
-
|
11
12
|
module Wrest
|
12
13
|
module AsyncRequest
|
13
14
|
# Loads Wrest eventmachine backend alongwith eventmachine gem
|
14
15
|
def self.enable_em
|
15
|
-
require
|
16
|
+
require 'wrest/async_request/event_machine_backend'
|
16
17
|
end
|
17
18
|
|
18
19
|
# Assign default backend to be used for asynchronous request. Default is to use threads
|
@@ -20,13 +21,13 @@ module Wrest
|
|
20
21
|
@default_backend = backend
|
21
22
|
end
|
22
23
|
|
23
|
-
# Assign default backend for asynchronous request to using eventmachine.
|
24
|
+
# Assign default backend for asynchronous request to using eventmachine.
|
24
25
|
def self.default_to_em!
|
25
|
-
|
26
|
+
enable_em
|
26
27
|
self.default_backend = Wrest::AsyncRequest::EventMachineBackend.new
|
27
28
|
end
|
28
29
|
|
29
|
-
# Assign default backend for asynchronous request to using threads.
|
30
|
+
# Assign default backend for asynchronous request to using threads.
|
30
31
|
def self.default_to_threads!(number_of_threads = 5)
|
31
32
|
self.default_backend = Wrest::AsyncRequest::ThreadBackend.new(number_of_threads)
|
32
33
|
end
|
@@ -35,7 +36,7 @@ module Wrest
|
|
35
36
|
def self.default_backend
|
36
37
|
@default_backend || default_to_threads!
|
37
38
|
end
|
38
|
-
|
39
|
+
|
39
40
|
# Uses Thread#join to wait until all background requests
|
40
41
|
# are completed.
|
41
42
|
#
|
data/lib/wrest/cache_proxy.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
module Wrest
|
3
4
|
class CacheProxy
|
4
5
|
class << self
|
5
6
|
def new(get, cache_store)
|
@@ -15,20 +16,21 @@ module Wrest
|
|
15
16
|
def initialize(get)
|
16
17
|
@get = get
|
17
18
|
end
|
19
|
+
|
18
20
|
def get
|
19
21
|
@get.invoke_without_cache_check
|
20
22
|
end
|
21
23
|
end
|
22
24
|
|
23
25
|
class DefaultCacheProxy
|
24
|
-
HOP_BY_HOP_HEADERS = [
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
26
|
+
HOP_BY_HOP_HEADERS = %w[connection
|
27
|
+
keep-alive
|
28
|
+
proxy-authenticate
|
29
|
+
proxy-authorization
|
30
|
+
te
|
31
|
+
trailers
|
32
|
+
transfer-encoding
|
33
|
+
upgrade].freeze
|
32
34
|
|
33
35
|
def initialize(get, cache_store)
|
34
36
|
@get = get
|
@@ -36,19 +38,15 @@ module Wrest
|
|
36
38
|
end
|
37
39
|
|
38
40
|
def log_cached_response
|
39
|
-
|
41
|
+
Wrest.logger.debug "<*> (GET #{@get.hash}) #{@get.uri.protocol}://#{@get.uri.host}:#{@get.uri.port}#{@get.http_request.path}"
|
40
42
|
end
|
41
|
-
|
43
|
+
|
42
44
|
def get
|
43
45
|
cached_response = @cache_store[@get.full_uri_string]
|
44
|
-
return
|
46
|
+
return fresh_get_response if cached_response.nil?
|
45
47
|
|
46
48
|
if cached_response.expired?
|
47
|
-
|
48
|
-
get_validated_response_for(cached_response)
|
49
|
-
else
|
50
|
-
get_fresh_response
|
51
|
-
end
|
49
|
+
expired_cached_response(cached_response)
|
52
50
|
else
|
53
51
|
log_cached_response
|
54
52
|
cached_response
|
@@ -57,15 +55,17 @@ module Wrest
|
|
57
55
|
|
58
56
|
def update_cache_headers_for(cached_response, new_response)
|
59
57
|
# RFC 2616 13.5.3 (Combining Headers)
|
60
|
-
cached_response.headers.merge!(new_response.headers.
|
58
|
+
cached_response.headers.merge!(new_response.headers.reject do |key, _value|
|
59
|
+
(HOP_BY_HOP_HEADERS.include? key.downcase)
|
60
|
+
end)
|
61
61
|
end
|
62
62
|
|
63
63
|
def cache(response)
|
64
|
-
@cache_store[@get.full_uri_string] = response.clone if response
|
64
|
+
@cache_store[@get.full_uri_string] = response.clone if response&.cacheable?
|
65
65
|
end
|
66
66
|
|
67
|
-
|
68
|
-
def
|
67
|
+
# :nodoc:
|
68
|
+
def fresh_get_response
|
69
69
|
@cache_store.delete @get.full_uri_string
|
70
70
|
|
71
71
|
response = @get.invoke_without_cache_check
|
@@ -75,10 +75,10 @@ module Wrest
|
|
75
75
|
response
|
76
76
|
end
|
77
77
|
|
78
|
-
|
78
|
+
# :nodoc:
|
79
79
|
def get_validated_response_for(cached_response)
|
80
80
|
new_response = send_validation_request_for(cached_response)
|
81
|
-
if new_response.code ==
|
81
|
+
if new_response.code == '304'
|
82
82
|
update_cache_headers_for(cached_response, new_response)
|
83
83
|
log_cached_response
|
84
84
|
cached_response
|
@@ -88,21 +88,32 @@ module Wrest
|
|
88
88
|
end
|
89
89
|
end
|
90
90
|
|
91
|
-
|
91
|
+
# :nodoc:
|
92
92
|
# Send a cache-validation request to the server. This would be the actual Get request with extra cache-validation headers.
|
93
93
|
# If a 304 (Not Modified) is received, Wrest would use the cached_response itself. Otherwise the new response is cached and used.
|
94
94
|
def send_validation_request_for(cached_response)
|
95
95
|
last_modified = cached_response.last_modified
|
96
|
-
etag = cached_response.headers[
|
96
|
+
etag = cached_response.headers['etag']
|
97
97
|
|
98
98
|
cache_validation_headers = {}
|
99
|
-
cache_validation_headers[
|
100
|
-
cache_validation_headers[
|
99
|
+
cache_validation_headers['if-modified-since'] = last_modified unless last_modified.nil?
|
100
|
+
cache_validation_headers['if-none-match'] = etag unless etag.nil?
|
101
101
|
|
102
102
|
new_request = @get.build_request_without_cache_store(cache_validation_headers)
|
103
103
|
|
104
104
|
new_request.invoke
|
105
105
|
end
|
106
|
+
|
107
|
+
private
|
108
|
+
|
109
|
+
# :nodoc:
|
110
|
+
def expired_cached_response(cached_response)
|
111
|
+
if cached_response.can_be_validated?
|
112
|
+
get_validated_response_for(cached_response)
|
113
|
+
else
|
114
|
+
fresh_get_response
|
115
|
+
end
|
116
|
+
end
|
106
117
|
end
|
107
118
|
end
|
108
|
-
end
|
119
|
+
end
|
@@ -1,34 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
begin
|
2
4
|
gem 'dalli', '~> 2'
|
3
5
|
rescue Gem::LoadError => e
|
4
|
-
Wrest.logger.debug
|
6
|
+
Wrest.logger.debug 'Dalli ~> 2 not found. The Dalli gem is necessary to use the memcached caching back-end.'
|
5
7
|
raise e
|
6
8
|
end
|
7
9
|
|
8
10
|
require 'dalli'
|
9
11
|
|
10
|
-
module Wrest
|
11
|
-
|
12
|
+
module Wrest
|
13
|
+
module Caching
|
14
|
+
class Memcached
|
15
|
+
def initialize(server_urls = nil, options = {})
|
16
|
+
@memcached = Dalli::Client.new(server_urls, options)
|
17
|
+
end
|
12
18
|
|
13
|
-
|
14
|
-
|
15
|
-
|
19
|
+
def [](key)
|
20
|
+
@memcached.get(key)
|
21
|
+
end
|
16
22
|
|
17
|
-
|
18
|
-
|
19
|
-
|
23
|
+
def []=(key, value)
|
24
|
+
@memcached.set(key, value)
|
25
|
+
end
|
20
26
|
|
21
|
-
|
22
|
-
|
23
|
-
|
27
|
+
# should be compatible with Hash - return value of the deleted element.
|
28
|
+
def delete(key)
|
29
|
+
value = self[key]
|
24
30
|
|
25
|
-
|
26
|
-
def delete(key)
|
27
|
-
value = self[key]
|
28
|
-
|
29
|
-
@memcached.delete key
|
31
|
+
@memcached.delete key
|
30
32
|
|
31
|
-
|
33
|
+
value
|
34
|
+
end
|
32
35
|
end
|
33
36
|
end
|
34
37
|
end
|
data/lib/wrest/caching/redis.rb
CHANGED
@@ -1,38 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
begin
|
2
4
|
gem 'redis', '~> 3'
|
3
5
|
rescue Gem::LoadError => e
|
4
|
-
Wrest.logger.debug
|
6
|
+
Wrest.logger.debug 'Redis ~> 3 not found. The Redis gem is necessary to use redis as a caching back-end.'
|
5
7
|
raise e
|
6
8
|
end
|
7
9
|
|
8
10
|
require 'redis'
|
9
11
|
require 'yaml'
|
10
12
|
|
11
|
-
module Wrest
|
12
|
-
|
13
|
+
module Wrest
|
14
|
+
module Caching
|
15
|
+
class Redis
|
16
|
+
def initialize(redis_options = {})
|
17
|
+
@redis = ::Redis.new(redis_options)
|
18
|
+
end
|
13
19
|
|
14
|
-
|
15
|
-
|
16
|
-
|
20
|
+
def [](key)
|
21
|
+
value = @redis.get(key)
|
22
|
+
value.nil? ? nil : YAML.unsafe_load(value)
|
23
|
+
end
|
17
24
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
25
|
+
def []=(key, response)
|
26
|
+
marshalled_response = YAML.dump(response)
|
27
|
+
@redis.set(key, marshalled_response)
|
28
|
+
@redis.expire(key, response.freshness_lifetime) unless response.expired?
|
29
|
+
end
|
23
30
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
@redis.expire(key, response.freshness_lifetime)
|
31
|
+
def delete(key)
|
32
|
+
value = self[key]
|
33
|
+
@redis.del(key)
|
34
|
+
value
|
29
35
|
end
|
30
36
|
end
|
31
|
-
|
32
|
-
def delete(key)
|
33
|
-
value = self[key]
|
34
|
-
@redis.del(key)
|
35
|
-
return value
|
36
|
-
end
|
37
37
|
end
|
38
38
|
end
|
data/lib/wrest/caching.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Copyright 2009 Sidu Ponnappa
|
2
4
|
|
3
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -9,42 +11,42 @@
|
|
9
11
|
|
10
12
|
module Wrest
|
11
13
|
module Caching
|
12
|
-
# Loads the Memcached caching back-end and the Dalli gem
|
14
|
+
# Loads the Memcached caching back-end and the Dalli gem
|
13
15
|
def self.enable_memcached
|
14
|
-
require
|
16
|
+
require 'wrest/caching/memcached'
|
15
17
|
end
|
16
|
-
|
17
|
-
# Loads the Redis caching back-end and the Redis gem
|
18
|
+
|
19
|
+
# Loads the Redis caching back-end and the Redis gem
|
18
20
|
def self.enable_redis
|
19
|
-
require
|
21
|
+
require 'wrest/caching/redis'
|
20
22
|
end
|
21
23
|
|
22
24
|
# Configures Wrest to cache all requests. This will use a Ruby Hash.
|
23
|
-
# WARNING: This should NEVER be used in a real environment. The Hash will
|
25
|
+
# WARNING: This should NEVER be used in a real environment. The Hash will
|
24
26
|
# keep growing since Wrest does not limit the size of a cache store.
|
25
27
|
#
|
26
28
|
# Please switch to the memcached or redis back-end for production use.
|
27
29
|
def self.default_to_hash!
|
28
|
-
self.default_store =
|
30
|
+
self.default_store = ({})
|
29
31
|
end
|
30
32
|
|
31
|
-
# Default Wrest to using memcached for caching requests.
|
33
|
+
# Default Wrest to using memcached for caching requests.
|
32
34
|
def self.default_to_memcached!
|
33
|
-
|
34
|
-
self.default_store = Wrest::Caching::Memcached.new
|
35
|
+
enable_memcached
|
36
|
+
self.default_store = Wrest::Caching::Memcached.new
|
35
37
|
end
|
36
|
-
|
38
|
+
|
37
39
|
# Default Wrest to using redis for caching requests.
|
38
|
-
#
|
40
|
+
#
|
39
41
|
# Options to configuring the redis gem can be passed as arguments.
|
40
42
|
def self.default_to_redis!(redis_options = {})
|
41
|
-
|
43
|
+
enable_redis
|
42
44
|
self.default_store = Wrest::Caching::Redis.new(redis_options)
|
43
45
|
end
|
44
46
|
|
45
47
|
# Assign the default cache store to be used. Default is none.
|
46
48
|
def self.default_store=(store)
|
47
|
-
@default_store = store
|
49
|
+
@default_store = store
|
48
50
|
end
|
49
51
|
|
50
52
|
# Returns the default store for caching, if any is set.
|