wrest 2.1.9 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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.
|