wrest 3.0.0 → 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 +3 -0
- data/LICENCE +1 -1
- data/README.md +29 -28
- 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 -96
- 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 -56
- data/lib/wrest/native/options.rb +15 -11
- data/lib/wrest/native/patch.rb +16 -12
- 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 -108
- data/lib/wrest/native/response.rb +87 -78
- data/lib/wrest/native/session.rb +49 -40
- data/lib/wrest/native.rb +14 -12
- 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 +70 -52
- 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 +98 -48
- 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,5 +1,8 @@
|
|
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
|
|
5
8
|
== 2.2.0
|
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,24 +1,36 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
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
|
10
24
|
* Supports RFC 2616 based [caching](https://github.com/kaiwren/wrest/blob/caching/Caching.markdown)
|
11
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
|
12
|
-
* Allows you to quickly build object oriented wrappers around any web service
|
13
|
-
* Is designed to be used as a library, not just a command line REST client (fewer class/static methods, more object oriented)
|
14
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
|
15
27
|
* Provides convenient HTTP wrappers, redirect handling, serialisation, deserialisation and xpath based lookup
|
16
28
|
|
17
|
-
|
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.
|
18
30
|
|
19
31
|
## Examples
|
20
32
|
|
21
|
-
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
|
22
34
|
|
23
35
|
### Basic Http Calls
|
24
36
|
|
@@ -27,10 +39,10 @@ For Facebook, Twitter, Delicious, GitHub and other API examples, see http://gith
|
|
27
39
|
* Basic API calls
|
28
40
|
|
29
41
|
```
|
30
|
-
# Works with json and xml out of the box
|
42
|
+
# Works with json and xml out of the box to give you a hash
|
31
43
|
# See lib/wrest/components/translators to add other formats
|
32
44
|
|
33
|
-
'https://api.github.com/repos/
|
45
|
+
'https://api.github.com/repos/rails/rails/issues'.to_uri.get.deserialize
|
34
46
|
```
|
35
47
|
|
36
48
|
* Timeout support
|
@@ -52,8 +64,6 @@ For Facebook, Twitter, Delicious, GitHub and other API examples, see http://gith
|
|
52
64
|
* Deserialise with XPath filtering
|
53
65
|
|
54
66
|
```
|
55
|
-
ActiveSupport::XmlMini.backend = 'REXML'
|
56
|
-
|
57
67
|
'http://twitter.com/statuses/public_timeline.xml'.to_uri.get.deserialise(
|
58
68
|
xpath: '//user/name/text()'
|
59
69
|
)
|
@@ -351,17 +361,6 @@ Detailed http debug logging can be turned on like so (DO NOT USE IN PRODUCTION!
|
|
351
361
|
'https://api.github.com/repos/c42/wrest/issues'.to_uri(detailed_http_logging: $stdout).get.deserialize
|
352
362
|
```
|
353
363
|
|
354
|
-
|
355
|
-
### Json Backend
|
356
|
-
|
357
|
-
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:
|
358
|
-
|
359
|
-
```
|
360
|
-
MultiJson.engine = :json_gem
|
361
|
-
```
|
362
|
-
|
363
|
-
For more information, look up the [multi_json](http://github.com/intridea/multi_json) documentation.
|
364
|
-
|
365
364
|
### Build
|
366
365
|
|
367
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.
|
@@ -433,3 +432,5 @@ Run the tests in a different terminal:
|
|
433
432
|
* Jacques Crocker : [railsjedi](http://github.com/railsjedi)
|
434
433
|
* Jasim A Basheer: [jasim](http://github.com/jasim)
|
435
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.
|
data/lib/wrest/callback.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");
|
@@ -12,12 +14,13 @@ module Wrest
|
|
12
14
|
attr_reader :callback_hash
|
13
15
|
|
14
16
|
def initialize(callable)
|
15
|
-
|
17
|
+
case callable
|
18
|
+
when Hash
|
16
19
|
@callback_hash = Callback.ensure_values_are_collections(callable)
|
17
|
-
|
20
|
+
when Proc
|
18
21
|
@callback_hash = {}
|
19
22
|
callable.call(self)
|
20
|
-
|
23
|
+
when Callback
|
21
24
|
@callback_hash = callable.callback_hash.dup
|
22
25
|
end
|
23
26
|
end
|
@@ -34,12 +37,12 @@ module Wrest
|
|
34
37
|
|
35
38
|
def execute(response)
|
36
39
|
callback_hash.each do |code, callback_list|
|
37
|
-
callback_list.each {|callback| callback.call(response)} if case code
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
40
|
+
callback_list.each { |callback| callback.call(response) } if case code
|
41
|
+
when Range
|
42
|
+
code.include?(response.code.to_i)
|
43
|
+
when Integer
|
44
|
+
code == response.code.to_i
|
45
|
+
end
|
43
46
|
end
|
44
47
|
end
|
45
48
|
|
@@ -47,14 +50,14 @@ module Wrest
|
|
47
50
|
@callback_hash[code] ? @callback_hash[code] << block : @callback_hash[code] = [block]
|
48
51
|
end
|
49
52
|
|
50
|
-
{200 =>
|
51
|
-
307 =>
|
52
|
-
406 =>
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
end
|
53
|
+
{ 200 => 'ok', 201 => 'created', 202 => 'accepted', 204 => 'no_content', 301 => 'moved_permanently', 302 => 'found', 303 => 'see_other', 304 => 'not_modified',
|
54
|
+
307 => 'temporary_redirect', 400 => 'bad_request', 401 => 'unauthorized', 403 => 'forbidden', 404 => 'not_found', 405 => 'method_not_allowed',
|
55
|
+
406 => 'not_acceptable', 422 => 'unprocessable_entity', 500 => 'internal_server_error' }.each do |code, method|
|
56
|
+
method_name = "on_#{method}".to_sym
|
57
|
+
define_method method_name do |&block|
|
58
|
+
(@callback_hash[code] ? @callback_hash[code] << block : @callback_hash[code] = [block]) if block
|
57
59
|
end
|
60
|
+
end
|
58
61
|
|
59
62
|
def self.ensure_values_are_collections(hash)
|
60
63
|
result = {}
|