faraday-http-cache 0.1.1 → 0.2.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 +7 -0
- data/LICENSE +1 -1
- data/README.md +2 -2
- data/lib/faraday/http_cache.rb +14 -8
- data/lib/faraday/http_cache/cache_control.rb +16 -19
- data/lib/faraday/http_cache/response.rb +10 -1
- data/lib/faraday/http_cache/storage.rb +1 -2
- data/spec/json_spec.rb +3 -6
- data/spec/middleware_spec.rb +27 -0
- data/spec/response_spec.rb +2 -2
- data/spec/storage_spec.rb +2 -2
- data/spec/support/test_app.rb +2 -2
- metadata +9 -23
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 03db6f441525313b0456fb22845a0273138a1c50
|
4
|
+
data.tar.gz: 7ede80de69498baf306b98be866b37f3b04e4683
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f3136959afbad718ce611169c3cf86f3721360c4b9bb44fca9db13fcca5e9013dc144a5a40f180ed904757c9e286c009bccd80672bb145fcde1769c84713acac
|
7
|
+
data.tar.gz: 4c66329f3810782ac4a586cc69d94e14ad4e1353b4cba5da928b8230a9821593a4be2ba538c20c4bb37baff75849a9ce2f30be5c7299f0bb7b562fcaeeadc6f5
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
[](https://travis-ci.org/plataformatec/faraday-http-cache)
|
4
4
|
|
5
|
-
a [Faraday](https://github.com/
|
5
|
+
a [Faraday](https://github.com/lostisland/faraday) middleware that respects HTTP cache,
|
6
6
|
by checking expiration and validation of the stored responses.
|
7
7
|
|
8
8
|
## Installation
|
@@ -73,4 +73,4 @@ Twitter API again.
|
|
73
73
|
|
74
74
|
## License
|
75
75
|
|
76
|
-
Copyright (c) 2012 Plataformatec. See LICENSE file.
|
76
|
+
Copyright (c) 2012-2013 Plataformatec. See LICENSE file.
|
data/lib/faraday/http_cache.rb
CHANGED
@@ -105,7 +105,7 @@ module Faraday
|
|
105
105
|
method == :get || method == :head
|
106
106
|
end
|
107
107
|
|
108
|
-
# Internal: Tries to
|
108
|
+
# Internal: Tries to locate a valid response or forwards the call to the stack.
|
109
109
|
# * If no entry is present on the storage, the 'fetch' method will forward
|
110
110
|
# the call to the remaining stack and return the new response.
|
111
111
|
# * If a fresh response is found, the middleware will abort the remaining
|
@@ -151,8 +151,10 @@ module Faraday
|
|
151
151
|
response = Response.new(env)
|
152
152
|
if response.not_modified?
|
153
153
|
trace :valid
|
154
|
-
|
155
|
-
response
|
154
|
+
updated_payload = entry.payload
|
155
|
+
updated_payload[:response_headers].update(response.payload[:response_headers])
|
156
|
+
env.update(updated_payload)
|
157
|
+
response = Response.new(updated_payload)
|
156
158
|
end
|
157
159
|
store(response)
|
158
160
|
end
|
@@ -204,7 +206,7 @@ module Faraday
|
|
204
206
|
# Returns a 'Hash' containing the ':status', ':body' and 'response_headers'
|
205
207
|
# entries.
|
206
208
|
def create_response(env)
|
207
|
-
env.slice(:status, :body, :response_headers)
|
209
|
+
env.to_hash.slice(:status, :body, :response_headers)
|
208
210
|
end
|
209
211
|
|
210
212
|
# Internal: Creates a new 'Hash' containing the request information.
|
@@ -214,8 +216,8 @@ module Faraday
|
|
214
216
|
# Returns a 'Hash' containing the ':method', ':url' and 'request_headers'
|
215
217
|
# entries.
|
216
218
|
def create_request(env)
|
217
|
-
request = env.slice(:method, :url)
|
218
|
-
request[:request_headers] =
|
219
|
+
request = env.to_hash.slice(:method, :url, :request_headers)
|
220
|
+
request[:request_headers] = request[:request_headers].dup
|
219
221
|
request
|
220
222
|
end
|
221
223
|
|
@@ -228,11 +230,15 @@ module Faraday
|
|
228
230
|
return unless @logger
|
229
231
|
|
230
232
|
method = @request[:method].to_s.upcase
|
231
|
-
path = @request[:url].
|
233
|
+
path = @request[:url].request_uri
|
232
234
|
line = "HTTP Cache: [#{method} #{path}] #{@trace.join(', ')}"
|
233
235
|
@logger.debug(line)
|
234
236
|
end
|
235
237
|
end
|
236
238
|
end
|
237
239
|
|
238
|
-
Faraday.register_middleware
|
240
|
+
if Faraday.respond_to?(:register_middleware)
|
241
|
+
Faraday.register_middleware :http_cache => Faraday::HttpCache
|
242
|
+
elsif Faraday::Middleware.respond_to?(:register_middleware)
|
243
|
+
Faraday::Middleware.register_middleware :http_cache => Faraday::HttpCache
|
244
|
+
end
|
@@ -7,9 +7,8 @@ module Faraday
|
|
7
7
|
class CacheControl
|
8
8
|
|
9
9
|
# Internal: Initialize a new CacheControl.
|
10
|
-
def initialize(
|
11
|
-
@directives =
|
12
|
-
parse(string)
|
10
|
+
def initialize(header)
|
11
|
+
@directives = parse(header.to_s)
|
13
12
|
end
|
14
13
|
|
15
14
|
# Internal: Checks if the 'public' directive is present.
|
@@ -79,33 +78,31 @@ module Faraday
|
|
79
78
|
|
80
79
|
private
|
81
80
|
|
82
|
-
# Internal: Parses the Cache Control string
|
83
|
-
# Existing
|
84
|
-
# For each
|
85
|
-
# and the
|
86
|
-
# present the assigned value will
|
81
|
+
# Internal: Parses the Cache Control string to a Hash.
|
82
|
+
# Existing whitespace will be removed and the string is split on commas.
|
83
|
+
# For each part everything before a '=' will be treated as the key
|
84
|
+
# and the exceeding will be treated as the value. If only the key is
|
85
|
+
# present then the assigned value will default to true.
|
87
86
|
#
|
88
87
|
# Examples:
|
89
88
|
# parse("max-age=600")
|
90
|
-
#
|
91
|
-
# # => { "max-age" => "600"}
|
89
|
+
# # => { "max-age" => "600"}
|
92
90
|
#
|
93
91
|
# parse("max-age")
|
94
|
-
#
|
95
|
-
# # => { "max-age" => true }
|
92
|
+
# # => { "max-age" => true }
|
96
93
|
#
|
97
|
-
# Returns
|
98
|
-
def parse(
|
99
|
-
|
94
|
+
# Returns a Hash.
|
95
|
+
def parse(header)
|
96
|
+
directives = {}
|
100
97
|
|
101
|
-
|
102
|
-
|
103
|
-
string.delete(' ').split(',').each do |part|
|
98
|
+
header.delete(' ').split(',').each do |part|
|
104
99
|
next if part.empty?
|
105
100
|
|
106
101
|
name, value = part.split('=', 2)
|
107
|
-
|
102
|
+
directives[name.downcase] = (value || true) unless name.empty?
|
108
103
|
end
|
104
|
+
|
105
|
+
directives
|
109
106
|
end
|
110
107
|
end
|
111
108
|
end
|
@@ -114,7 +114,16 @@ module Faraday
|
|
114
114
|
#
|
115
115
|
# Returns a new instance of a 'Faraday::Response' with the payload.
|
116
116
|
def to_response(env)
|
117
|
-
|
117
|
+
env.update(@payload)
|
118
|
+
Faraday::Response.new(env)
|
119
|
+
end
|
120
|
+
|
121
|
+
# Internal: Exposes a representation of the current
|
122
|
+
# payload that we can serialize and cache properly.
|
123
|
+
#
|
124
|
+
# Returns a 'Hash'.
|
125
|
+
def serializable_hash
|
126
|
+
@payload.slice(:status, :body, :response_headers)
|
118
127
|
end
|
119
128
|
|
120
129
|
private
|
@@ -32,8 +32,7 @@ module Faraday
|
|
32
32
|
# response - The Faraday::HttpCache::Response instance to be stored.
|
33
33
|
def write(request, response)
|
34
34
|
key = cache_key_for(request)
|
35
|
-
value = MultiJson.dump(response.
|
36
|
-
|
35
|
+
value = MultiJson.dump(response.serializable_hash)
|
37
36
|
cache.write(key, value)
|
38
37
|
end
|
39
38
|
|
data/spec/json_spec.rb
CHANGED
@@ -6,19 +6,16 @@ describe Faraday::HttpCache do
|
|
6
6
|
let(:client) do
|
7
7
|
Faraday.new(:url => ENV['FARADAY_SERVER']) do |stack|
|
8
8
|
stack.response :json, :content_type => /\bjson$/
|
9
|
-
stack.use
|
9
|
+
stack.use :http_cache, :logger => logger
|
10
10
|
adapter = ENV['FARADAY_ADAPTER']
|
11
11
|
stack.headers['X-Faraday-Adapter'] = adapter
|
12
12
|
stack.adapter adapter.to_sym
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
before do
|
17
|
-
client.get('clear')
|
18
|
-
end
|
19
|
-
|
20
16
|
it "works fine with other middlewares" do
|
17
|
+
client.get('clear')
|
21
18
|
client.get('json').body['count'].should == 1
|
22
19
|
client.get('json').body['count'].should == 1
|
23
20
|
end
|
24
|
-
end
|
21
|
+
end
|
data/spec/middleware_spec.rb
CHANGED
@@ -83,6 +83,13 @@ describe Faraday::HttpCache do
|
|
83
83
|
client.get('get')
|
84
84
|
end
|
85
85
|
|
86
|
+
it "differs requests with different query strings in the log" do
|
87
|
+
logger.should_receive(:debug).with('HTTP Cache: [GET /get] miss, store')
|
88
|
+
logger.should_receive(:debug).with('HTTP Cache: [GET /get?q=what] miss, store')
|
89
|
+
client.get('get')
|
90
|
+
client.get('get', :q => "what")
|
91
|
+
end
|
92
|
+
|
86
93
|
it "logs that a stored GET response is fresh" do
|
87
94
|
client.get('get')
|
88
95
|
logger.should_receive(:debug).with('HTTP Cache: [GET /get] fresh')
|
@@ -121,6 +128,26 @@ describe Faraday::HttpCache do
|
|
121
128
|
date.should =~ /^\w{3}, \d{2} \w{3} \d{4} \d{2}:\d{2}:\d{2} GMT$/
|
122
129
|
end
|
123
130
|
|
131
|
+
it "updates the 'Cache-Control' header when a response is validated" do
|
132
|
+
cache_control = client.get('etag').headers['Cache-Control']
|
133
|
+
client.get('etag').headers['Cache-Control'].should_not == cache_control
|
134
|
+
end
|
135
|
+
|
136
|
+
it "updates the 'Date' header when a response is validated" do
|
137
|
+
date = client.get('etag').headers['Date']
|
138
|
+
client.get('etag').headers['Date'].should_not == date
|
139
|
+
end
|
140
|
+
|
141
|
+
it "updates the 'Expires' header when a response is validated" do
|
142
|
+
expires = client.get('etag').headers['Expires']
|
143
|
+
client.get('etag').headers['Expires'].should_not == expires
|
144
|
+
end
|
145
|
+
|
146
|
+
it "updates the 'Vary' header when a response is validated" do
|
147
|
+
vary = client.get('etag').headers['Vary']
|
148
|
+
client.get('etag').headers['Vary'].should_not == vary
|
149
|
+
end
|
150
|
+
|
124
151
|
describe 'Configuration options' do
|
125
152
|
let(:app) { double("it's an app!") }
|
126
153
|
|
data/spec/response_spec.rb
CHANGED
@@ -128,12 +128,12 @@ describe Faraday::HttpCache::Response do
|
|
128
128
|
|
129
129
|
describe "response unboxing" do
|
130
130
|
subject { described_class.new(:status => 200, :response_headers => {}, :body => "Hi!") }
|
131
|
-
let(:env) { { :resquest => mock } }
|
132
131
|
|
132
|
+
let(:env) { { :method => :get } }
|
133
133
|
let(:response) { subject.to_response(env) }
|
134
134
|
|
135
135
|
it "merges the supplied env object with the response data" do
|
136
|
-
response.env[:
|
136
|
+
response.env[:method].should be
|
137
137
|
end
|
138
138
|
|
139
139
|
it "returns a Faraday::Response" do
|
data/spec/storage_spec.rb
CHANGED
@@ -5,7 +5,7 @@ describe Faraday::HttpCache::Storage do
|
|
5
5
|
{ :method => :get, :request_headers => {}, :url => URI.parse("http://foo.bar/") }
|
6
6
|
end
|
7
7
|
|
8
|
-
let(:response) { double(:
|
8
|
+
let(:response) { double(:serializable_hash => {}) }
|
9
9
|
|
10
10
|
let(:cache) { ActiveSupport::Cache.lookup_store }
|
11
11
|
|
@@ -20,7 +20,7 @@ describe Faraday::HttpCache::Storage do
|
|
20
20
|
|
21
21
|
describe 'storing responses' do
|
22
22
|
it 'writes the response json to the underlying cache using a digest as the key' do
|
23
|
-
json = MultiJson.dump(response.
|
23
|
+
json = MultiJson.dump(response.serializable_hash)
|
24
24
|
|
25
25
|
cache.should_receive(:write).with('503ac9f7180ca1cdec49e8eb73a9cc0b47c27325', json)
|
26
26
|
subject.write(request, response)
|
data/spec/support/test_app.rb
CHANGED
@@ -69,9 +69,9 @@ class TestApp < Sinatra::Base
|
|
69
69
|
tag = settings.counter > 2 ? '1' : '2'
|
70
70
|
|
71
71
|
if env['HTTP_IF_NONE_MATCH'] == tag
|
72
|
-
[304, { 'ETag' => tag }, ""]
|
72
|
+
[304, { 'ETag' => tag, 'Cache-Control' => 'max-age=200', 'Date' => Time.now.httpdate, 'Expires' => (Time.now + 200).httpdate, 'Vary' => '*' }, ""]
|
73
73
|
else
|
74
|
-
[200, { 'ETag' => tag }, "#{settings.requests += 1}"]
|
74
|
+
[200, { 'ETag' => tag, 'Cache-Control' => 'max-age=0', 'Date' => settings.yesterday, 'Expires' => Time.now.httpdate, 'Vary' => 'Accept' }, "#{settings.requests += 1}"]
|
75
75
|
end
|
76
76
|
end
|
77
77
|
end
|
metadata
CHANGED
@@ -1,36 +1,32 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: faraday-http-cache
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.2.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Lucas Mazza
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2013-06-03 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: activesupport
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - '>='
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '3.0'
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - '>='
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: '3.0'
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: faraday
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
31
|
- - ~>
|
36
32
|
- !ruby/object:Gem::Version
|
@@ -38,7 +34,6 @@ dependencies:
|
|
38
34
|
type: :runtime
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
38
|
- - ~>
|
44
39
|
- !ruby/object:Gem::Version
|
@@ -46,7 +41,6 @@ dependencies:
|
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: multi_json
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
45
|
- - ~>
|
52
46
|
- !ruby/object:Gem::Version
|
@@ -54,7 +48,6 @@ dependencies:
|
|
54
48
|
type: :runtime
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
52
|
- - ~>
|
60
53
|
- !ruby/object:Gem::Version
|
@@ -83,33 +76,26 @@ files:
|
|
83
76
|
- spec/support/test_server.rb
|
84
77
|
homepage: https://github.com/plataformatec/faraday-http-cache
|
85
78
|
licenses: []
|
79
|
+
metadata: {}
|
86
80
|
post_install_message:
|
87
81
|
rdoc_options: []
|
88
82
|
require_paths:
|
89
83
|
- lib
|
90
84
|
required_ruby_version: !ruby/object:Gem::Requirement
|
91
|
-
none: false
|
92
85
|
requirements:
|
93
|
-
- -
|
86
|
+
- - '>='
|
94
87
|
- !ruby/object:Gem::Version
|
95
88
|
version: '0'
|
96
|
-
segments:
|
97
|
-
- 0
|
98
|
-
hash: -4216884502397664395
|
99
89
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
100
|
-
none: false
|
101
90
|
requirements:
|
102
|
-
- -
|
91
|
+
- - '>='
|
103
92
|
- !ruby/object:Gem::Version
|
104
93
|
version: '0'
|
105
|
-
segments:
|
106
|
-
- 0
|
107
|
-
hash: -4216884502397664395
|
108
94
|
requirements: []
|
109
95
|
rubyforge_project:
|
110
|
-
rubygems_version:
|
96
|
+
rubygems_version: 2.0.0
|
111
97
|
signing_key:
|
112
|
-
specification_version:
|
98
|
+
specification_version: 4
|
113
99
|
summary: A Faraday middleware that stores and validates cache expiration.
|
114
100
|
test_files:
|
115
101
|
- spec/cache_control_spec.rb
|