wrest 3.0.0 → 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 +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 = {}
|