faraday-manual-cache 0.1.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.circleci/config.yml +9 -0
- data/.rspec +2 -0
- data/README.md +20 -10
- data/faraday-manual-cache.gemspec +5 -1
- data/lib/faraday-manual-cache/configuration.rb +18 -0
- data/lib/faraday-manual-cache/version.rb +3 -0
- data/lib/faraday/manual_cache.rb +27 -21
- data/spec/manual_cache_spec.rb +126 -0
- data/spec/spec_helper.rb +20 -0
- metadata +38 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 5687d1ea9b8a6e476067698ee92e5ad59249d6744589d97d2ccfd7f0ddc17447
|
4
|
+
data.tar.gz: 8a90c333880ef44bc400347f76e44121628c43fe4ec4a7d7b3adfa1d537c9391
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bc1dbefa346aa1999e4491abfe42a575b9670d9861656f2728670a404f062056e5f76e5f70ff4e9969bed5452f51d8428a2dac7cef38ea600dd518de6cd6d7d8
|
7
|
+
data.tar.gz: cd7847c0c26d2a9eb0f3427901555bf0114db9c37fb10512c0fc7cb86b58a961551766efda5f5d09cb69c819d32feb355a27f9056965b0a7f87568e0b5fdcd04
|
data/.rspec
ADDED
data/README.md
CHANGED
@@ -18,9 +18,19 @@ Or install it yourself as:
|
|
18
18
|
|
19
19
|
$ gem install faraday-manual-cache
|
20
20
|
|
21
|
+
## Configuration
|
22
|
+
|
23
|
+
Create a configuration file and select your memory store class. If you use Rails, just create an initializator.
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
FaradayManualCache.configure do |config|
|
27
|
+
config.memory_store = ActiveSupport::Cache::MemoryStore.new
|
28
|
+
end
|
29
|
+
```
|
30
|
+
|
21
31
|
## Usage
|
22
32
|
|
23
|
-
Super simple example that caches using the default store (`MemoryStore`) for the default expires_in (30 seconds):
|
33
|
+
Super simple example that caches using the default store (`MemoryStore`) for the default expires_in (30 seconds):
|
24
34
|
|
25
35
|
```ruby
|
26
36
|
require 'faraday'
|
@@ -33,29 +43,29 @@ end
|
|
33
43
|
```
|
34
44
|
The middleware currently takes several options:
|
35
45
|
|
46
|
+
* `conditions`: Conditional caching (default GET and HEAD requests).
|
47
|
+
* `cache_key`: Key for requests comparison (default URL)
|
36
48
|
* `expires_in`: Cache expiry, in seconds (default 30).
|
37
|
-
* `
|
38
|
-
* `store_options`: Options passed to the store if created by lookup (e.g. when specifying `:memory_store`, `:redis_store`, etc).
|
49
|
+
* `logger`: Specify a logger to enable logging.
|
39
50
|
|
40
51
|
So a more complicated example would be:
|
41
52
|
|
42
53
|
```ruby
|
43
54
|
require 'faraday'
|
44
55
|
require 'faraday-manual-cache'
|
45
|
-
require 'redis-rails'
|
46
56
|
|
47
57
|
connection = Faraday.new(url: 'http://example.com') do |builder|
|
48
|
-
builder.use :manual_cache,
|
58
|
+
builder.use :manual_cache,
|
59
|
+
conditions: ->(env) { env.method == :get },
|
60
|
+
cache_key: ->(env) { "prefix-#{env.url}" },
|
61
|
+
expires_in: 10,
|
62
|
+
logger: Rails.logger
|
49
63
|
builder.adapter Faraday.default_adapter
|
50
64
|
end
|
51
65
|
```
|
52
66
|
|
53
67
|
As with `faraday-http-cache` it's recommended that `faraday-manual-cache` be fairly low in the middleware stack.
|
54
68
|
|
55
|
-
## TODO
|
56
|
-
|
57
|
-
* Additional cache key options.
|
58
|
-
|
59
69
|
## Contributing
|
60
70
|
|
61
71
|
1. Fork it ( http://github.com/dobs/faraday-manual-cache/fork )
|
@@ -70,4 +80,4 @@ Some implementation details taken from [`faraday-http-cache`](https://github.com
|
|
70
80
|
|
71
81
|
## Contributors
|
72
82
|
|
73
|
-
* Maintainer: [Daniel O'Brien](http://github.com/dobs)
|
83
|
+
* Maintainer: [Daniel O'Brien](http://github.com/dobs)
|
@@ -1,7 +1,10 @@
|
|
1
1
|
# coding: utf-8
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require 'faraday-manual-cache/version'
|
4
|
+
|
2
5
|
Gem::Specification.new do |spec|
|
3
6
|
spec.name = 'faraday-manual-cache'
|
4
|
-
spec.version =
|
7
|
+
spec.version = FaradayManualCache::VERSION
|
5
8
|
spec.authors = ['Daniel O\'Brien']
|
6
9
|
spec.email = ['dan@dobs.org']
|
7
10
|
spec.summary = %q(A super simple Faraday cache implementation.)
|
@@ -21,4 +24,5 @@ Gem::Specification.new do |spec|
|
|
21
24
|
|
22
25
|
spec.add_development_dependency 'bundler', '~> 1.5'
|
23
26
|
spec.add_development_dependency 'rake'
|
27
|
+
spec.add_development_dependency 'rspec'
|
24
28
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module FaradayManualCache
|
2
|
+
class << self
|
3
|
+
attr_accessor :configuration
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.configure
|
7
|
+
self.configuration ||= Configuration.new
|
8
|
+
yield(configuration)
|
9
|
+
end
|
10
|
+
|
11
|
+
class Configuration
|
12
|
+
attr_accessor :memory_store
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@memory_store = ActiveSupport::Cache::MemoryStore.new
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/faraday/manual_cache.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'faraday-manual-cache/configuration'
|
1
2
|
require 'faraday'
|
2
3
|
|
3
4
|
module Faraday
|
@@ -8,26 +9,22 @@ module Faraday
|
|
8
9
|
#
|
9
10
|
# Currently accepts four arguments:
|
10
11
|
#
|
12
|
+
# :conditions - Conditional caching based on a lambda (default: GET/HEAD
|
13
|
+
# requests)
|
11
14
|
# :expires_in - Cache expiry, in seconds (default: 30).
|
12
15
|
# :logger - A logger object to send cache hit/miss/write messages.
|
13
|
-
|
14
|
-
# ActiveSupport::Cache::Store instance. (default:
|
15
|
-
# MemoryStore).
|
16
|
-
# :store_options - Options to pass to the store when generated based on a
|
17
|
-
# lookup symvol (default: {}).
|
16
|
+
|
18
17
|
class ManualCache < Faraday::Middleware
|
18
|
+
DEFAULT_CONDITIONS = ->(env) { env.method == :get || env.method == :head }
|
19
|
+
DEFAULT_CACHE_KEY = ->(env) { env.url }
|
20
|
+
|
19
21
|
def initialize(app, *args)
|
20
22
|
super(app)
|
21
23
|
options = args.first || {}
|
24
|
+
@conditions = options.fetch(:conditions, DEFAULT_CONDITIONS)
|
22
25
|
@expires_in = options.fetch(:expires_in, 30)
|
23
26
|
@logger = options.fetch(:logger, nil)
|
24
|
-
@
|
25
|
-
@store = options.fetch(:store, :memory_store)
|
26
|
-
@store_options = options.fetch(:store_options, {})
|
27
|
-
|
28
|
-
@store_options[:namespace] ||= @namespace
|
29
|
-
|
30
|
-
initialize_store
|
27
|
+
@cache_key = options.fetch(:cache_key, DEFAULT_CACHE_KEY)
|
31
28
|
end
|
32
29
|
|
33
30
|
def call(env)
|
@@ -41,7 +38,7 @@ module Faraday
|
|
41
38
|
|
42
39
|
if response_env
|
43
40
|
response_env.response_headers['x-faraday-manual-cache'] = 'HIT'
|
44
|
-
to_response(
|
41
|
+
to_response(response_env)
|
45
42
|
else
|
46
43
|
@app.call(env).on_complete do |response_env|
|
47
44
|
response_env.response_headers['x-faraday-manual-cache'] = 'MISS'
|
@@ -54,20 +51,28 @@ module Faraday
|
|
54
51
|
return unless cacheable?(env) && !env.request_headers['x-faraday-manual-cache']
|
55
52
|
|
56
53
|
info "Cache WRITE: #{key(env)}"
|
57
|
-
|
54
|
+
store.write(
|
55
|
+
key(env),
|
56
|
+
env,
|
57
|
+
expires_in: expires_in(env)
|
58
|
+
)
|
58
59
|
end
|
59
60
|
|
60
61
|
def cacheable?(env)
|
61
|
-
|
62
|
+
@conditions.call(env)
|
62
63
|
end
|
63
64
|
|
64
65
|
def cached_response(env)
|
65
|
-
|
66
|
+
if cacheable?(env) && !env.request_headers['x-faraday-manual-cache']
|
67
|
+
response_env = store.fetch(key(env))
|
68
|
+
end
|
69
|
+
|
66
70
|
if response_env
|
67
71
|
info "Cache HIT: #{key(env)}"
|
68
72
|
else
|
69
73
|
info "Cache MISS: #{key(env)}"
|
70
74
|
end
|
75
|
+
|
71
76
|
response_env
|
72
77
|
end
|
73
78
|
|
@@ -76,14 +81,15 @@ module Faraday
|
|
76
81
|
end
|
77
82
|
|
78
83
|
def key(env)
|
79
|
-
env
|
84
|
+
@cache_key.call(env)
|
80
85
|
end
|
81
86
|
|
82
|
-
def
|
83
|
-
|
87
|
+
def expires_in(env)
|
88
|
+
@expires_in.respond_to?(:call) ? @expires_in.call(env) : @expires_in
|
89
|
+
end
|
84
90
|
|
85
|
-
|
86
|
-
@store
|
91
|
+
def store
|
92
|
+
@store ||= FaradayManualCache.configuration.memory_store
|
87
93
|
end
|
88
94
|
|
89
95
|
def to_response(env)
|
@@ -0,0 +1,126 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'faraday-manual-cache'
|
3
|
+
require 'active_support'
|
4
|
+
|
5
|
+
class MockStore
|
6
|
+
def fetch(*args) end
|
7
|
+
def write(*args) end
|
8
|
+
end
|
9
|
+
|
10
|
+
RSpec.describe Faraday::ManualCache do
|
11
|
+
let(:stubs) do
|
12
|
+
Faraday::Adapter::Test::Stubs.new do |stub|
|
13
|
+
stub.get('/') { |_| [200, {}, ''] }
|
14
|
+
stub.head('/') { |_| [200, {}, ''] }
|
15
|
+
stub.post('/') { |_| [200, {}, ''] }
|
16
|
+
stub.put('/') { |_| [200, {}, ''] }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
let(:store) { ActiveSupport::Cache::MemoryStore.new }
|
20
|
+
let(:configuration_double) { double(:configuration_double, memory_store: store) }
|
21
|
+
|
22
|
+
before do
|
23
|
+
allow(FaradayManualCache).to receive(:configuration).and_return(configuration_double)
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'basic configuration' do
|
27
|
+
subject do
|
28
|
+
Faraday.new(url: 'http://www.example.com') do |faraday|
|
29
|
+
faraday.use :manual_cache
|
30
|
+
faraday.adapter :test, stubs
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should cache on GET' do
|
35
|
+
expect(store).to receive(:fetch)
|
36
|
+
expect(store).to receive(:write)
|
37
|
+
subject.get('/')
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should cache on HEAD' do
|
41
|
+
expect(store).to receive(:fetch)
|
42
|
+
expect(store).to receive(:write)
|
43
|
+
subject.head('/')
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should not cache on POST' do
|
47
|
+
expect(store).not_to receive(:fetch)
|
48
|
+
expect(store).not_to receive(:write)
|
49
|
+
subject.post('/')
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should not cache on PUT' do
|
53
|
+
expect(store).not_to receive(:fetch)
|
54
|
+
expect(store).not_to receive(:write)
|
55
|
+
subject.put('/')
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'conditional configuration' do
|
60
|
+
subject do
|
61
|
+
Faraday.new(url: 'http://www.example.com') do |faraday|
|
62
|
+
faraday.use :manual_cache, conditions: ->(_) { true }
|
63
|
+
faraday.adapter :test, stubs
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should cache on GET' do
|
68
|
+
expect(store).to receive(:fetch)
|
69
|
+
expect(store).to receive(:write)
|
70
|
+
subject.get('/')
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should cache on HEAD' do
|
74
|
+
expect(store).to receive(:fetch)
|
75
|
+
expect(store).to receive(:write)
|
76
|
+
subject.head('/')
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'should cache on POST' do
|
80
|
+
expect(store).to receive(:fetch)
|
81
|
+
expect(store).to receive(:write)
|
82
|
+
subject.post('/')
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should cache on PUT' do
|
86
|
+
expect(store).to receive(:fetch)
|
87
|
+
expect(store).to receive(:write)
|
88
|
+
subject.put('/')
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context 'conditional configuration with cache key' do
|
93
|
+
subject do
|
94
|
+
Faraday.new(url: 'http://www.example.com') do |faraday|
|
95
|
+
faraday.use :manual_cache,
|
96
|
+
conditions: ->(_) { true },
|
97
|
+
cache_key: ->(env) { "prefix-#{env.url}" }
|
98
|
+
faraday.adapter :test, stubs
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'should cache based of cache_key' do
|
103
|
+
expect(store).to receive(:fetch)
|
104
|
+
expect(store).to receive(:write).with('prefix-http://www.example.com/', any_args)
|
105
|
+
subject.get('/')
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
context 'dynamic configuration with expires in' do
|
110
|
+
subject do
|
111
|
+
Faraday.new(url: 'http://www.example.com') do |faraday|
|
112
|
+
faraday.use :manual_cache,
|
113
|
+
conditions: ->(_) { true },
|
114
|
+
cache_key: ->(env) { "prefix-#{env.url}" },
|
115
|
+
expires_in: ->(env) { env.status * 2 }
|
116
|
+
faraday.adapter :test, stubs
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'should cache with ttl based on lambda' do
|
121
|
+
expect(store).to receive(:fetch)
|
122
|
+
expect(store).to receive(:write).with('prefix-http://www.example.com/', any_args, expires_in: 400)
|
123
|
+
subject.get('/')
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
RSpec.configure do |config|
|
2
|
+
config.expect_with :rspec do |expectations|
|
3
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
4
|
+
end
|
5
|
+
|
6
|
+
config.mock_with :rspec do |mocks|
|
7
|
+
mocks.verify_partial_doubles = true
|
8
|
+
end
|
9
|
+
|
10
|
+
config.shared_context_metadata_behavior = :apply_to_host_groups
|
11
|
+
config.filter_run_when_matching :focus
|
12
|
+
config.disable_monkey_patching!
|
13
|
+
|
14
|
+
if config.files_to_run.one?
|
15
|
+
config.default_formatter = 'doc'
|
16
|
+
end
|
17
|
+
|
18
|
+
config.order = :random
|
19
|
+
Kernel.srand config.seed
|
20
|
+
end
|
metadata
CHANGED
@@ -1,69 +1,83 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: faraday-manual-cache
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel O'Brien
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-02-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: 3.0.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 3.0.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: faraday
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - ~>
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0.9'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - ~>
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0.9'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: bundler
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - ~>
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '1.5'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - ~>
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '1.5'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rake
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
67
81
|
- !ruby/object:Gem::Version
|
68
82
|
version: '0'
|
69
83
|
description: A super simple Faraday cache implementation.
|
@@ -73,15 +87,21 @@ executables: []
|
|
73
87
|
extensions: []
|
74
88
|
extra_rdoc_files: []
|
75
89
|
files:
|
76
|
-
- .
|
77
|
-
- .
|
90
|
+
- ".circleci/config.yml"
|
91
|
+
- ".gitignore"
|
92
|
+
- ".rspec"
|
93
|
+
- ".rubocop.yml"
|
78
94
|
- Gemfile
|
79
95
|
- LICENSE.txt
|
80
96
|
- README.md
|
81
97
|
- Rakefile
|
82
98
|
- faraday-manual-cache.gemspec
|
83
99
|
- lib/faraday-manual-cache.rb
|
100
|
+
- lib/faraday-manual-cache/configuration.rb
|
101
|
+
- lib/faraday-manual-cache/version.rb
|
84
102
|
- lib/faraday/manual_cache.rb
|
103
|
+
- spec/manual_cache_spec.rb
|
104
|
+
- spec/spec_helper.rb
|
85
105
|
homepage: https://github.com/dobs/faraday-manual-cache
|
86
106
|
licenses:
|
87
107
|
- MIT
|
@@ -92,18 +112,20 @@ require_paths:
|
|
92
112
|
- lib
|
93
113
|
required_ruby_version: !ruby/object:Gem::Requirement
|
94
114
|
requirements:
|
95
|
-
- -
|
115
|
+
- - ">="
|
96
116
|
- !ruby/object:Gem::Version
|
97
117
|
version: '1.9'
|
98
118
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
119
|
requirements:
|
100
|
-
- -
|
120
|
+
- - ">="
|
101
121
|
- !ruby/object:Gem::Version
|
102
122
|
version: '0'
|
103
123
|
requirements: []
|
104
124
|
rubyforge_project:
|
105
|
-
rubygems_version: 2.
|
125
|
+
rubygems_version: 2.7.8
|
106
126
|
signing_key:
|
107
127
|
specification_version: 4
|
108
128
|
summary: A super simple Faraday cache implementation.
|
109
|
-
test_files:
|
129
|
+
test_files:
|
130
|
+
- spec/manual_cache_spec.rb
|
131
|
+
- spec/spec_helper.rb
|