resterl 0.0.14 → 0.0.15
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 +4 -4
- data/lib/resterl/client.rb +32 -27
- data/lib/resterl/delete_request.rb +1 -1
- data/lib/resterl/generic_request.rb +47 -39
- data/lib/resterl/get_request.rb +1 -1
- data/lib/resterl/post_request.rb +1 -1
- data/lib/resterl/put_request.rb +1 -1
- data/lib/resterl/response.rb +28 -25
- data/lib/resterl/version.rb +1 -1
- data/resterl.gemspec +5 -2
- data/spec/lib/resterl/client.rb +36 -0
- data/spec/spec_helper.rb +2 -0
- metadata +63 -7
- data/test/helper.rb +0 -10
- data/test/test_resterl.rb +0 -57
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 065a5323c4a08bb01e76e6985f2d7c119633526b
|
4
|
+
data.tar.gz: b2d8eee11d66bdecb0c7cf82ab86ba4c48062965
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 986afceceddfdc2fb116c3a4fdc7c2d0653b80c66bf52487d472f4ce12f2b0b943a7485eb7675f98ab9bcd60390067268bbdda00aa60b621012880a0a0f449d4
|
7
|
+
data.tar.gz: 19ea49a89a3022dc99ad064b83c4a9ac3501c9d5000ea34fbb159919ac8c84250f296cff78ea9db116360d3d8e6302cb6a8ada33fa58d19db2fcb56164aa1fb8
|
data/lib/resterl/client.rb
CHANGED
@@ -66,38 +66,33 @@ module Resterl
|
|
66
66
|
private
|
67
67
|
|
68
68
|
def new_get_request url, cache_key, params, headers, old_response
|
69
|
-
|
70
|
-
if old_response
|
71
|
-
etag = old_response.net_http_response['ETag']
|
72
|
-
headers['If-None-Match'] = etag if etag
|
73
|
-
|
74
|
-
last_modified = old_response.net_http_response['Last-Modified']
|
75
|
-
headers['If-Modified-Since'] = last_modified if last_modified
|
76
|
-
end
|
69
|
+
apply_conditional_headers(headers, old_response)
|
77
70
|
|
78
71
|
# Anfrage stellen, ggf. ETag mit übergeben
|
79
72
|
request = Resterl::GetRequest.new(self, url, params, headers)
|
80
73
|
new_response = request.perform.response
|
81
74
|
|
82
|
-
response, max_age_seconds =
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
75
|
+
response, max_age_seconds =
|
76
|
+
case new_response
|
77
|
+
when Net::HTTPClientError,
|
78
|
+
Net::HTTPServerError
|
79
|
+
# Aus dem Cache muss nichts entfernt werden,
|
80
|
+
# weil ja auch kein Eintrag (mehr) drin ist.
|
81
|
+
new_response.error!
|
82
|
+
when Net::HTTPNotModified
|
83
|
+
# Wenn "304 Not Modified", dann altes
|
84
|
+
# Ergebnis als neues Ergebnis verwenden
|
85
|
+
r_temp = Resterl::Response.new(new_response)
|
86
|
+
old_response.update_expires_at(
|
87
|
+
r_temp.expires_at)
|
88
|
+
[old_response, r_temp.expires_at - Time.now]
|
89
|
+
when Net::HTTPSuccess
|
90
|
+
r = Resterl::Response.new(new_response,
|
91
|
+
options[:minimum_cache_lifetime])
|
92
|
+
[r, r.expires_at - Time.now]
|
93
|
+
else
|
94
|
+
raise 'unknown response'
|
95
|
+
end
|
101
96
|
|
102
97
|
# Cachezeit berechnen
|
103
98
|
expiry = [
|
@@ -111,6 +106,16 @@ module Resterl
|
|
111
106
|
response
|
112
107
|
end
|
113
108
|
|
109
|
+
# Ggf. ETag und Last-Modified auslesen
|
110
|
+
def apply_conditional_headers(headers, old_response)
|
111
|
+
return unless old_response
|
112
|
+
etag = old_response.net_http_response['ETag']
|
113
|
+
headers['If-None-Match'] = etag if etag
|
114
|
+
|
115
|
+
last_modified = old_response.net_http_response['Last-Modified']
|
116
|
+
headers['If-Modified-Since'] = last_modified if last_modified
|
117
|
+
end
|
118
|
+
|
114
119
|
def setup_url url
|
115
120
|
if url =~ /^http/
|
116
121
|
url
|
@@ -6,7 +6,7 @@ class Resterl::DeleteRequest < Resterl::GenericRequest
|
|
6
6
|
@data = data
|
7
7
|
end
|
8
8
|
def perform
|
9
|
-
http, path =
|
9
|
+
http, path = http_object_and_query_path
|
10
10
|
request = Net::HTTP::Delete.new path, @headers
|
11
11
|
apply_basic_auth request
|
12
12
|
self.response = http.request(request)
|
@@ -1,45 +1,53 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
def get_http_object_and_query_path
|
15
|
-
uri = URI.parse(url)
|
16
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
17
|
-
apply_ssl http, uri
|
18
|
-
|
19
|
-
path_with_query = uri.path
|
20
|
-
path_with_query << "?#{query_param_string}" unless query_param_string.blank?
|
21
|
-
|
22
|
-
[http, path_with_query]
|
23
|
-
end
|
24
|
-
|
25
|
-
def query_param_string
|
26
|
-
@query_param_string ||= begin
|
27
|
-
@query_params.collect do |key, value|
|
28
|
-
"#{URI.escape(key.to_s)}=#{URI.escape(value.to_s)}"
|
29
|
-
end.join('&')
|
1
|
+
require 'active_support/core_ext/object/blank'
|
2
|
+
|
3
|
+
module Resterl
|
4
|
+
class GenericRequest
|
5
|
+
attr_accessor :rest_client, :url, :body, :response
|
6
|
+
DEFAULT_HEADERS = {}
|
7
|
+
|
8
|
+
def initialize client, url, query_params, headers
|
9
|
+
@rest_client = client
|
10
|
+
@url = url
|
11
|
+
@query_params = query_params
|
12
|
+
@headers = DEFAULT_HEADERS.merge headers
|
30
13
|
end
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def http_object_and_query_path
|
18
|
+
uri = URI.parse(url)
|
19
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
20
|
+
apply_ssl http, uri
|
21
|
+
|
22
|
+
path_with_query = uri.path
|
23
|
+
unless query_param_string.blank?
|
24
|
+
path_with_query << "?#{query_param_string}"
|
25
|
+
end
|
26
|
+
|
27
|
+
[http, path_with_query]
|
28
|
+
end
|
29
|
+
|
30
|
+
def query_param_string
|
31
|
+
@query_param_string ||= begin
|
32
|
+
@query_params.collect do |key, value|
|
33
|
+
"#{URI.escape(key.to_s)}=#{URI.escape(value.to_s)}"
|
34
|
+
end.join('&')
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def apply_basic_auth request
|
39
|
+
ba = rest_client.options[:basic_auth]
|
40
|
+
request.basic_auth(ba[:username], ba[:password]) if ba
|
41
|
+
end
|
42
|
+
|
43
|
+
def apply_ssl http, uri
|
44
|
+
return unless uri.is_a? URI::HTTPS
|
38
45
|
http.use_ssl = true
|
39
46
|
http.verify_mode = rest_client.options[:ssl_verify_mode]
|
40
47
|
end
|
48
|
+
|
49
|
+
def redirect_url
|
50
|
+
response['location'] || response.body.match(/<a href=\"([^>]+)\">/i)[1]
|
51
|
+
end
|
41
52
|
end
|
42
|
-
def redirect_url
|
43
|
-
response['location'] || response.body.match(/<a href=\"([^>]+)\">/i)[1]
|
44
|
-
end
|
45
53
|
end
|
data/lib/resterl/get_request.rb
CHANGED
@@ -11,7 +11,7 @@ class Resterl::GetRequest < Resterl::GenericRequest
|
|
11
11
|
def perform
|
12
12
|
raise TooManyRedirects if redirect_limit < 0
|
13
13
|
|
14
|
-
http, path =
|
14
|
+
http, path = http_object_and_query_path
|
15
15
|
request = Net::HTTP::Get.new path, @headers
|
16
16
|
apply_basic_auth request
|
17
17
|
self.response = http.request(request)
|
data/lib/resterl/post_request.rb
CHANGED
@@ -4,7 +4,7 @@ class Resterl::PostRequest < Resterl::GenericRequest
|
|
4
4
|
@data = data
|
5
5
|
end
|
6
6
|
def perform
|
7
|
-
http, path =
|
7
|
+
http, path = http_object_and_query_path
|
8
8
|
request = Net::HTTP::Post.new path, @headers
|
9
9
|
apply_basic_auth request
|
10
10
|
request.body = @data
|
data/lib/resterl/put_request.rb
CHANGED
@@ -6,7 +6,7 @@ class Resterl::PutRequest < Resterl::GenericRequest
|
|
6
6
|
@data = data
|
7
7
|
end
|
8
8
|
def perform
|
9
|
-
http, path =
|
9
|
+
http, path = http_object_and_query_path
|
10
10
|
request = Net::HTTP::Put.new path, @headers
|
11
11
|
apply_basic_auth request
|
12
12
|
request.body = @data
|
data/lib/resterl/response.rb
CHANGED
@@ -1,33 +1,36 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
module Resterl
|
2
|
+
class Response
|
3
|
+
attr_reader :body, :expires_at, :net_http_response
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
end
|
5
|
+
def initialize(r, minimum_cache_lifetime)
|
6
|
+
@net_http_response = r
|
7
|
+
@body = r.body
|
8
|
+
@expires_at = Time.now + [extract_max_age, minimum_cache_lifetime].max
|
9
|
+
end
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
def expired?
|
12
|
+
@expires_at < Time.now
|
13
|
+
end
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
# rubocop:disable Style/TrivialAccessors
|
16
|
+
def update_expires_at t
|
17
|
+
@expires_at = t
|
18
|
+
end
|
19
|
+
# rubocop:enable Style/TrivialAccessors
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
-
|
21
|
+
def header h
|
22
|
+
@net_http_response[h]
|
23
|
+
end
|
22
24
|
|
23
|
-
|
24
|
-
|
25
|
-
|
25
|
+
def expires_in
|
26
|
+
extract_max_age
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
26
30
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
cc.is_a?(String) ? cc[/max-age=(\d+)/, 1].to_i : 0
|
31
|
+
def extract_max_age
|
32
|
+
cc = @net_http_response['Cache-Control']
|
33
|
+
cc.is_a?(String) ? cc[/max-age=(\d+)/, 1].to_i : 0
|
34
|
+
end
|
32
35
|
end
|
33
36
|
end
|
data/lib/resterl/version.rb
CHANGED
data/resterl.gemspec
CHANGED
@@ -15,8 +15,11 @@ Gem::Specification.new do |s|
|
|
15
15
|
s.executables = `git ls-files -- bin/*`.split("\n").map{|f|File.basename(f)}
|
16
16
|
#s.require_paths = ["lib"]
|
17
17
|
|
18
|
+
s.add_runtime_dependency 'activesupport', '>= 2.3.18'
|
18
19
|
s.add_runtime_dependency 'hashie', '~> 0.4.0'
|
19
20
|
s.add_runtime_dependency 'yajl-ruby', '~> 1.1'
|
20
|
-
s.add_development_dependency '
|
21
|
+
s.add_development_dependency 'rspec', '~> 3.1'
|
22
|
+
s.add_development_dependency 'webmock', '~> 1.20.4'
|
23
|
+
s.add_development_dependency 'timecop', '~> 0.7.1'
|
24
|
+
s.add_development_dependency 'pry'
|
21
25
|
end
|
22
|
-
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require_relative '../../spec_helper'
|
2
|
+
|
3
|
+
require 'webmock/rspec'
|
4
|
+
require 'timecop'
|
5
|
+
|
6
|
+
describe Resterl::Client do
|
7
|
+
|
8
|
+
describe 'minimum cache lifetime' do
|
9
|
+
|
10
|
+
before do
|
11
|
+
Timecop.freeze(Time.parse('2015-01-01 01:00'))
|
12
|
+
|
13
|
+
stub_request(:get, 'http://www.example.com/').to_return(
|
14
|
+
status: 200,
|
15
|
+
body: 'hello world',
|
16
|
+
headers: { cache_control: 'max-age=0, private, must-revalidate' }
|
17
|
+
).then.to_raise('2 requests')
|
18
|
+
end
|
19
|
+
let(:client) { Resterl::Client.new }
|
20
|
+
|
21
|
+
it 'is used in "max-age=0" case' do
|
22
|
+
response = client.get 'http://www.example.com/', {}, {}
|
23
|
+
expect(response.expires_at).to eq Time.parse('2015-01-01 01:05')
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'uses the caches' do
|
27
|
+
client.get 'http://www.example.com/', {}, {}
|
28
|
+
|
29
|
+
Timecop.freeze(Time.parse('2015-01-01 01:00:10'))
|
30
|
+
|
31
|
+
expect do
|
32
|
+
client.get 'http://www.example.com/', {}, {}
|
33
|
+
end.not_to raise_error
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: resterl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.15
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Florian Dütsch
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-02-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 2.3.18
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 2.3.18
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: hashie
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -39,7 +53,49 @@ dependencies:
|
|
39
53
|
- !ruby/object:Gem::Version
|
40
54
|
version: '1.1'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.1'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.1'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: webmock
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ~>
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 1.20.4
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ~>
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 1.20.4
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: timecop
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ~>
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.7.1
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ~>
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 0.7.1
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: pry
|
43
99
|
requirement: !ruby/object:Gem::Requirement
|
44
100
|
requirements:
|
45
101
|
- - '>='
|
@@ -83,8 +139,8 @@ files:
|
|
83
139
|
- lib/resterl/response.rb
|
84
140
|
- lib/resterl/version.rb
|
85
141
|
- resterl.gemspec
|
86
|
-
-
|
87
|
-
-
|
142
|
+
- spec/lib/resterl/client.rb
|
143
|
+
- spec/spec_helper.rb
|
88
144
|
homepage: http://github.com/Nix-wie-weg/resterl
|
89
145
|
licenses: []
|
90
146
|
metadata: {}
|
@@ -109,6 +165,6 @@ signing_key:
|
|
109
165
|
specification_version: 4
|
110
166
|
summary: Rudimentary HTTP client with focus on caching
|
111
167
|
test_files:
|
112
|
-
-
|
113
|
-
-
|
168
|
+
- spec/lib/resterl/client.rb
|
169
|
+
- spec/spec_helper.rb
|
114
170
|
has_rdoc:
|
data/test/helper.rb
DELETED
data/test/test_resterl.rb
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
class TestResterl < Test::Unit::TestCase
|
4
|
-
|
5
|
-
should 'load successfully' do
|
6
|
-
dummy = nil
|
7
|
-
cache = Resterl::Caches::KeyPrefixDecorator.new(
|
8
|
-
Resterl::Caches::RailsMemcachedCache.new(dummy),
|
9
|
-
'prefix_'
|
10
|
-
)
|
11
|
-
|
12
|
-
|
13
|
-
ODIN_CLIENT = Resterl::Client.new(
|
14
|
-
:base_uri => 'http://www.google.com/',
|
15
|
-
:cache => cache
|
16
|
-
)
|
17
|
-
end
|
18
|
-
|
19
|
-
context 'BaseObject' do
|
20
|
-
should 'provide class level inheritable attributes' do
|
21
|
-
|
22
|
-
assert_nil Resterl::BaseObject.resterl_client
|
23
|
-
assert_nil Resterl::BaseObject.complete_mime_type
|
24
|
-
|
25
|
-
assert_nothing_raised do
|
26
|
-
class Test < Resterl::BaseObject
|
27
|
-
self.resterl_client = nil
|
28
|
-
self.complete_mime_type = 'text/plain'
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
end
|
33
|
-
|
34
|
-
should 'work with deeper nestings (cattr_inheritable)' do
|
35
|
-
|
36
|
-
assert_nothing_raised do
|
37
|
-
|
38
|
-
class Test::BaseObject < Resterl::BaseObject
|
39
|
-
self.mime_type = :json
|
40
|
-
self.resterl_client = 1
|
41
|
-
end
|
42
|
-
|
43
|
-
class Test::T1 < Test::BaseObject
|
44
|
-
|
45
|
-
end
|
46
|
-
|
47
|
-
|
48
|
-
Test::T1.complete_mime_type
|
49
|
-
Test::T1.resterl_client
|
50
|
-
|
51
|
-
end
|
52
|
-
|
53
|
-
end
|
54
|
-
|
55
|
-
end
|
56
|
-
|
57
|
-
end
|