resterl 0.0.14 → 0.0.15

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e927695ca56a351455ca5ea51eab5201f4663ba3
4
- data.tar.gz: 24d36643d33e40fe72f08496b27874bb8cccb1bd
3
+ metadata.gz: 065a5323c4a08bb01e76e6985f2d7c119633526b
4
+ data.tar.gz: b2d8eee11d66bdecb0c7cf82ab86ba4c48062965
5
5
  SHA512:
6
- metadata.gz: d3c59e6dd212727d2c538d5fe1cc530eef15d45303c385c8f273f0df8977d1e8800022eb760aaeb399e0dc20454f5c581fecb1a327f07c77d26339d2015bad88
7
- data.tar.gz: 34313e88f25883f86d235fca6c5467a0b124c3d07f4493643e1941ae7e553510ae314cfd0f36d120bc7dd3341f16b35e7084d91dded394176ddbf0083be39006
6
+ metadata.gz: 986afceceddfdc2fb116c3a4fdc7c2d0653b80c66bf52487d472f4ce12f2b0b943a7485eb7675f98ab9bcd60390067268bbdda00aa60b621012880a0a0f449d4
7
+ data.tar.gz: 19ea49a89a3022dc99ad064b83c4a9ac3501c9d5000ea34fbb159919ac8c84250f296cff78ea9db116360d3d8e6302cb6a8ada33fa58d19db2fcb56164aa1fb8
@@ -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
- # Ggf. ETag und Last-Modified auslesen
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 = case new_response
83
- when Net::HTTPClientError,
84
- Net::HTTPServerError
85
- # Aus dem Cache muss nichts entfernt werden,
86
- # weil ja auch kein Eintrag (mehr) drin ist.
87
- new_response.error!
88
- when Net::HTTPNotModified
89
- # Wenn "304 Not Modified", dann altes
90
- # Ergebnis als neues Ergebnis verwenden
91
- r_temp = Resterl::Response.new(new_response)
92
- old_response.update_expires_at(
93
- r_temp.expires_at)
94
- [old_response, r_temp.expires_at - Time.now]
95
- when Net::HTTPSuccess
96
- r = Resterl::Response.new(new_response)
97
- [r, r.expires_at - Time.now]
98
- else
99
- raise 'unknown response'
100
- end
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 = get_http_object_and_query_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
- class Resterl::GenericRequest
2
- attr_accessor :rest_client, :url, :body, :response
3
- DEFAULT_HEADERS = {}
4
-
5
- def initialize client, url, query_params, headers
6
- @rest_client = client
7
- @url = url
8
- @query_params = query_params
9
- @headers = DEFAULT_HEADERS.merge headers
10
- end
11
-
12
- private
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
- end
32
- def apply_basic_auth request
33
- ba = rest_client.options[:basic_auth]
34
- request.basic_auth(ba[:username], ba[:password]) if ba
35
- end
36
- def apply_ssl http, uri
37
- if uri.is_a? URI::HTTPS
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
@@ -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 = get_http_object_and_query_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)
@@ -4,7 +4,7 @@ class Resterl::PostRequest < Resterl::GenericRequest
4
4
  @data = data
5
5
  end
6
6
  def perform
7
- http, path = get_http_object_and_query_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
@@ -6,7 +6,7 @@ class Resterl::PutRequest < Resterl::GenericRequest
6
6
  @data = data
7
7
  end
8
8
  def perform
9
- http, path = get_http_object_and_query_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
@@ -1,33 +1,36 @@
1
- class Resterl::Response
2
- attr_reader :body, :expires_at, :net_http_response
1
+ module Resterl
2
+ class Response
3
+ attr_reader :body, :expires_at, :net_http_response
3
4
 
4
- def initialize(r)
5
- @net_http_response = r
6
- @body = r.body
7
- #@expires_in = extract_max_age
8
- @expires_at = Time.now + extract_max_age
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
- def expired?
12
- @expires_at < Time.now
13
- end
11
+ def expired?
12
+ @expires_at < Time.now
13
+ end
14
14
 
15
- def update_expires_at t
16
- @expires_at = t
17
- end
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
- def header h
20
- @net_http_response[h]
21
- end
21
+ def header h
22
+ @net_http_response[h]
23
+ end
22
24
 
23
- def expires_in
24
- extract_max_age
25
- end
25
+ def expires_in
26
+ extract_max_age
27
+ end
28
+
29
+ private
26
30
 
27
- private
28
-
29
- def extract_max_age
30
- cc = @net_http_response['Cache-Control']
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
@@ -1,3 +1,3 @@
1
1
  module Resterl
2
- VERSION = '0.0.14'
2
+ VERSION = '0.0.15'
3
3
  end
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 'shoulda'
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
@@ -0,0 +1,2 @@
1
+ require_relative '../lib/resterl'
2
+ require 'pry'
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.14
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: 2014-10-21 00:00:00.000000000 Z
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: shoulda
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
- - test/helper.rb
87
- - test/test_resterl.rb
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
- - test/helper.rb
113
- - test/test_resterl.rb
168
+ - spec/lib/resterl/client.rb
169
+ - spec/spec_helper.rb
114
170
  has_rdoc:
data/test/helper.rb DELETED
@@ -1,10 +0,0 @@
1
- require 'rubygems'
2
- require 'test/unit'
3
- require 'shoulda'
4
-
5
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
- $LOAD_PATH.unshift(File.dirname(__FILE__))
7
- require 'resterl'
8
-
9
- class Test::Unit::TestCase
10
- end
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