padrino-cache 0.18.0 → 0.18.2
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/padrino-cache/helpers/page.rb +24 -11
- data/padrino-cache.gemspec +8 -3
- data/test/test_padrino_cache.rb +157 -0
- metadata +13 -9
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fbd32a2e65add5d5f0e143fb98a411b78c5926e97cd56f5bc6d5ea0976ab4fee
|
|
4
|
+
data.tar.gz: 36af9ade2e7efc5a564f8e243f900998e5b77c48b8b71472b1753c0ea6f9100f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 555e89a1b630f754c12fa127fda89c84beb18965a74290af21d9f798a298479a06d367674f3a14f7aa95b1204791ac2d559d3e0faec419a89da3832304a7174d
|
|
7
|
+
data.tar.gz: 1bfb38bbc845d74631f20c5f82c60d136acad4689584dfd830d256452bb6bff092c563b463e6aba3df67dd5b212ff298537d6c79ad317f46df9b775d0b2772cb
|
|
@@ -60,7 +60,7 @@ module Padrino
|
|
|
60
60
|
#
|
|
61
61
|
# @api public
|
|
62
62
|
def expires(time)
|
|
63
|
-
@
|
|
63
|
+
@_cache_expires = time
|
|
64
64
|
end
|
|
65
65
|
|
|
66
66
|
##
|
|
@@ -89,7 +89,11 @@ module Padrino
|
|
|
89
89
|
#
|
|
90
90
|
def cache_key(name = nil, &block)
|
|
91
91
|
raise 'Can not provide both cache_key and a block' if name && block
|
|
92
|
-
|
|
92
|
+
|
|
93
|
+
@_cache_key = name || block
|
|
94
|
+
# A Symbol or a block is the same for every request, so later requests can look it up before the
|
|
95
|
+
# handler runs. Any other key (a String built from params) belongs to this request only.
|
|
96
|
+
@route.cache_key = @_cache_key if @_cache_key.is_a?(Symbol) || @_cache_key.is_a?(Proc)
|
|
93
97
|
end
|
|
94
98
|
|
|
95
99
|
CACHED_VERBS = { 'GET' => true, 'HEAD' => true }.freeze
|
|
@@ -97,21 +101,30 @@ module Padrino
|
|
|
97
101
|
def self.padrino_route_added(route, verb, *)
|
|
98
102
|
return unless route.cache && CACHED_VERBS[verb]
|
|
99
103
|
|
|
100
|
-
route
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
end
|
|
104
|
+
# Remember the key and expiry set before this route (by an app-level before filter), so a route
|
|
105
|
+
# reached through pass starts from them rather than from this route's.
|
|
106
|
+
route.before_filters { @_cache_outer = [@_cache_key, @_cache_expires] }
|
|
107
|
+
# The lookup is the route's last condition: it runs after every before filter and condition, so
|
|
108
|
+
# access checks written there apply to cached pages too.
|
|
109
|
+
route.custom_conditions << instance_method(:serve_cached_response)
|
|
107
110
|
|
|
108
111
|
route.after_filters do
|
|
109
|
-
save_cached_response(route.cache_expires) if settings.caching?
|
|
112
|
+
save_cached_response(@_cache_expires.nil? ? route.cache_expires : @_cache_expires) if settings.caching?
|
|
113
|
+
@_cache_key, @_cache_expires = @_cache_outer
|
|
110
114
|
end
|
|
111
115
|
end
|
|
112
116
|
|
|
113
117
|
private
|
|
114
118
|
|
|
119
|
+
def serve_cached_response
|
|
120
|
+
if settings.caching? && (cached_response = load_cached_response)
|
|
121
|
+
env['sinatra.route'] = "#{request.request_method} #{@route.sinatra_pattern}"
|
|
122
|
+
content_type cached_response[:content_type]
|
|
123
|
+
halt 200, cached_response[:body]
|
|
124
|
+
end
|
|
125
|
+
true
|
|
126
|
+
end
|
|
127
|
+
|
|
115
128
|
def load_cached_response
|
|
116
129
|
began_at = Time.now
|
|
117
130
|
route_cache_key = resolve_cache_key || env['PATH_INFO']
|
|
@@ -142,7 +155,7 @@ module Padrino
|
|
|
142
155
|
# Resolve the cache_key when it's a block in the correct context.
|
|
143
156
|
#
|
|
144
157
|
def resolve_cache_key
|
|
145
|
-
key = @route.cache_key
|
|
158
|
+
key = @_cache_key || @route.cache_key
|
|
146
159
|
key.is_a?(Proc) ? instance_eval(&key) : key
|
|
147
160
|
end
|
|
148
161
|
|
data/padrino-cache.gemspec
CHANGED
|
@@ -8,16 +8,21 @@ Gem::Specification.new do |s|
|
|
|
8
8
|
s.authors = ['Padrino Team', 'Nathan Esquenazi', "Davide D'Agostino", 'Arthur Chiu']
|
|
9
9
|
s.email = 'padrinorb@gmail.com'
|
|
10
10
|
s.summary = 'Page and fragment caching for Padrino'
|
|
11
|
-
s.homepage = '
|
|
11
|
+
s.homepage = 'https://padrinorb.com'
|
|
12
12
|
s.description = 'Caching support for memcached, page and fragment'
|
|
13
|
+
s.required_ruby_version = '>= 2.7.8'
|
|
13
14
|
s.required_rubygems_version = '>= 1.3.6'
|
|
14
15
|
s.version = Padrino.version
|
|
15
|
-
s.date = Time.now.strftime('%Y-%m-%d')
|
|
16
16
|
s.license = 'MIT'
|
|
17
|
+
s.metadata = {
|
|
18
|
+
'bug_tracker_uri' => 'https://github.com/padrino/padrino-framework/issues',
|
|
19
|
+
'changelog_uri' => 'https://github.com/padrino/padrino-framework/blob/master/CHANGES.rdoc',
|
|
20
|
+
'documentation_uri' => 'https://padrinorb.com/guides/',
|
|
21
|
+
'source_code_uri' => 'https://github.com/padrino/padrino-framework'
|
|
22
|
+
}
|
|
17
23
|
|
|
18
24
|
s.extra_rdoc_files = Dir['*.rdoc']
|
|
19
25
|
s.files = `git ls-files`.split("\n")
|
|
20
|
-
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
21
26
|
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
|
22
27
|
s.require_paths = ['lib']
|
|
23
28
|
s.rdoc_options = ['--charset=UTF-8']
|
data/test/test_padrino_cache.rb
CHANGED
|
@@ -6,6 +6,19 @@ describe 'PadrinoCache' do
|
|
|
6
6
|
`rm -rf #{tmp}`
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
+
it 'names a page served from the cache in sinatra.route' do
|
|
10
|
+
routes = []
|
|
11
|
+
mock_app do
|
|
12
|
+
register Padrino::Cache
|
|
13
|
+
enable :caching
|
|
14
|
+
get('/page/:id', cache: true) { "page #{params[:id]}" }
|
|
15
|
+
after { routes << env['sinatra.route'] }
|
|
16
|
+
end
|
|
17
|
+
2.times { get '/page/1' }
|
|
18
|
+
assert_equal 'page 1', body
|
|
19
|
+
assert_equal ['GET /page/:id', 'GET /page/:id'], routes
|
|
20
|
+
end
|
|
21
|
+
|
|
9
22
|
it 'should cache a fragment' do
|
|
10
23
|
called = false
|
|
11
24
|
mock_app do
|
|
@@ -381,6 +394,150 @@ describe 'PadrinoCache' do
|
|
|
381
394
|
assert_equal 2, call_count
|
|
382
395
|
end
|
|
383
396
|
|
|
397
|
+
it 'should not reuse a string cache key from another request' do
|
|
398
|
+
mock_app do
|
|
399
|
+
register Padrino::Cache
|
|
400
|
+
enable :caching
|
|
401
|
+
get '/post/:id', cache: true do
|
|
402
|
+
cache_key "post-#{params[:id]}"
|
|
403
|
+
"post #{params[:id]}"
|
|
404
|
+
end
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
get '/post/1'
|
|
408
|
+
assert_equal 'post 1', body
|
|
409
|
+
get '/post/2'
|
|
410
|
+
assert_equal 'post 2', body
|
|
411
|
+
get '/post/1'
|
|
412
|
+
assert_equal 'post 1', body
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
it 'should run controller before filters on a cached response' do
|
|
416
|
+
mock_app do
|
|
417
|
+
register Padrino::Cache
|
|
418
|
+
enable :caching
|
|
419
|
+
controller :secret, cache: true do
|
|
420
|
+
before { halt 403, 'denied' unless params[:ok] }
|
|
421
|
+
get(:index) { 'secret page' }
|
|
422
|
+
end
|
|
423
|
+
end
|
|
424
|
+
|
|
425
|
+
get '/secret?ok=1'
|
|
426
|
+
assert_equal 'secret page', body
|
|
427
|
+
get '/secret'
|
|
428
|
+
assert_equal 403, status
|
|
429
|
+
assert_equal 'denied', body
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
it 'should use a cache key set in a controller before filter for the lookup' do
|
|
433
|
+
calls = 0
|
|
434
|
+
mock_app do
|
|
435
|
+
register Padrino::Cache
|
|
436
|
+
enable :caching
|
|
437
|
+
controller :users, cache: true do
|
|
438
|
+
before { cache_key "user-#{params[:u]}" }
|
|
439
|
+
get(:show, with: :u) { calls += 1; "user #{params[:u]}" }
|
|
440
|
+
end
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
get '/users/show/a'
|
|
444
|
+
get '/users/show/b'
|
|
445
|
+
get '/users/show/a'
|
|
446
|
+
assert_equal 'user a', body
|
|
447
|
+
assert_equal 2, calls
|
|
448
|
+
end
|
|
449
|
+
|
|
450
|
+
it 'should not apply a cache key to the next route after pass' do
|
|
451
|
+
mock_app do
|
|
452
|
+
register Padrino::Cache
|
|
453
|
+
enable :caching
|
|
454
|
+
get '/x/:id', cache: true do
|
|
455
|
+
cache_key :shared
|
|
456
|
+
pass if params[:id] == 'skip'
|
|
457
|
+
"A #{params[:id]}"
|
|
458
|
+
end
|
|
459
|
+
get('/x/:id', cache: true) { "B #{params[:id]}" }
|
|
460
|
+
end
|
|
461
|
+
|
|
462
|
+
get '/x/skip'
|
|
463
|
+
assert_equal 'B skip', body
|
|
464
|
+
get '/x/1'
|
|
465
|
+
assert_equal 'A 1', body
|
|
466
|
+
end
|
|
467
|
+
|
|
468
|
+
it 'should check route conditions on a cached response' do
|
|
469
|
+
mock_app do
|
|
470
|
+
register Padrino::Cache
|
|
471
|
+
enable :caching
|
|
472
|
+
def self.protect(protected)
|
|
473
|
+
condition { halt 403, 'No secrets for you!' unless params[:key] == 's3cr3t' } if protected
|
|
474
|
+
end
|
|
475
|
+
controller cache: true, conditions: { protect: true } do
|
|
476
|
+
get('/private') { 'secret stuff' }
|
|
477
|
+
end
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
get '/private?key=s3cr3t'
|
|
481
|
+
assert_equal 'secret stuff', body
|
|
482
|
+
get '/private'
|
|
483
|
+
assert_equal 403, status
|
|
484
|
+
assert_equal 'No secrets for you!', body
|
|
485
|
+
end
|
|
486
|
+
|
|
487
|
+
it 'should keep a cache key from an app-level before filter for the route reached through pass' do
|
|
488
|
+
mock_app do
|
|
489
|
+
register Padrino::Cache
|
|
490
|
+
enable :caching
|
|
491
|
+
before { cache_key "u-#{params[:u]}" }
|
|
492
|
+
get('/z', cache: true) { pass }
|
|
493
|
+
get('/z', cache: true) { "B for #{params[:u]}" }
|
|
494
|
+
end
|
|
495
|
+
|
|
496
|
+
get '/z?u=alice'
|
|
497
|
+
assert_equal 'B for alice', body
|
|
498
|
+
get '/z?u=bob'
|
|
499
|
+
assert_equal 'B for bob', body
|
|
500
|
+
end
|
|
501
|
+
|
|
502
|
+
it 'should keep expires to the request that set it' do
|
|
503
|
+
stored = []
|
|
504
|
+
store = Object.new
|
|
505
|
+
store.define_singleton_method(:[]) { |_key| nil }
|
|
506
|
+
store.define_singleton_method(:store) { |key, _value, options| stored << [key, options[:expires]] }
|
|
507
|
+
mock_app do
|
|
508
|
+
register Padrino::Cache
|
|
509
|
+
enable :caching
|
|
510
|
+
set :cache, store
|
|
511
|
+
get '/foo', cache: true do
|
|
512
|
+
expires 100 if params[:long]
|
|
513
|
+
'foo'
|
|
514
|
+
end
|
|
515
|
+
end
|
|
516
|
+
|
|
517
|
+
get '/foo?long=1'
|
|
518
|
+
get '/foo'
|
|
519
|
+
assert_equal [['/foo', 100], ['/foo', nil]], stored
|
|
520
|
+
end
|
|
521
|
+
|
|
522
|
+
it 'should let expires false in a handler override the route expiry' do
|
|
523
|
+
stored = []
|
|
524
|
+
store = Object.new
|
|
525
|
+
store.define_singleton_method(:[]) { |_key| nil }
|
|
526
|
+
store.define_singleton_method(:store) { |key, _value, options| stored << [key, options[:expires]] }
|
|
527
|
+
mock_app do
|
|
528
|
+
register Padrino::Cache
|
|
529
|
+
enable :caching
|
|
530
|
+
set :cache, store
|
|
531
|
+
get '/ef', cache: true, expires: 60 do
|
|
532
|
+
expires false
|
|
533
|
+
'ef'
|
|
534
|
+
end
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
get '/ef'
|
|
538
|
+
assert_equal [['/ef', false]], stored
|
|
539
|
+
end
|
|
540
|
+
|
|
384
541
|
it 'should resolve block cache keys' do
|
|
385
542
|
call_count = 0
|
|
386
543
|
mock_app do
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: padrino-cache
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.18.
|
|
4
|
+
version: 0.18.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Padrino Team
|
|
@@ -11,7 +11,7 @@ authors:
|
|
|
11
11
|
autorequire:
|
|
12
12
|
bindir: bin
|
|
13
13
|
cert_chain: []
|
|
14
|
-
date: 2026-
|
|
14
|
+
date: 2026-11-01 00:00:00.000000000 Z
|
|
15
15
|
dependencies:
|
|
16
16
|
- !ruby/object:Gem::Dependency
|
|
17
17
|
name: padrino-core
|
|
@@ -19,28 +19,28 @@ dependencies:
|
|
|
19
19
|
requirements:
|
|
20
20
|
- - '='
|
|
21
21
|
- !ruby/object:Gem::Version
|
|
22
|
-
version: 0.18.
|
|
22
|
+
version: 0.18.2
|
|
23
23
|
type: :runtime
|
|
24
24
|
prerelease: false
|
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
|
26
26
|
requirements:
|
|
27
27
|
- - '='
|
|
28
28
|
- !ruby/object:Gem::Version
|
|
29
|
-
version: 0.18.
|
|
29
|
+
version: 0.18.2
|
|
30
30
|
- !ruby/object:Gem::Dependency
|
|
31
31
|
name: padrino-helpers
|
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
|
33
33
|
requirements:
|
|
34
34
|
- - '='
|
|
35
35
|
- !ruby/object:Gem::Version
|
|
36
|
-
version: 0.18.
|
|
36
|
+
version: 0.18.2
|
|
37
37
|
type: :runtime
|
|
38
38
|
prerelease: false
|
|
39
39
|
version_requirements: !ruby/object:Gem::Requirement
|
|
40
40
|
requirements:
|
|
41
41
|
- - '='
|
|
42
42
|
- !ruby/object:Gem::Version
|
|
43
|
-
version: 0.18.
|
|
43
|
+
version: 0.18.2
|
|
44
44
|
- !ruby/object:Gem::Dependency
|
|
45
45
|
name: moneta
|
|
46
46
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -77,10 +77,14 @@ files:
|
|
|
77
77
|
- test/helper.rb
|
|
78
78
|
- test/test_moneta_store.rb
|
|
79
79
|
- test/test_padrino_cache.rb
|
|
80
|
-
homepage:
|
|
80
|
+
homepage: https://padrinorb.com
|
|
81
81
|
licenses:
|
|
82
82
|
- MIT
|
|
83
|
-
metadata:
|
|
83
|
+
metadata:
|
|
84
|
+
bug_tracker_uri: https://github.com/padrino/padrino-framework/issues
|
|
85
|
+
changelog_uri: https://github.com/padrino/padrino-framework/blob/master/CHANGES.rdoc
|
|
86
|
+
documentation_uri: https://padrinorb.com/guides/
|
|
87
|
+
source_code_uri: https://github.com/padrino/padrino-framework
|
|
84
88
|
post_install_message:
|
|
85
89
|
rdoc_options:
|
|
86
90
|
- "--charset=UTF-8"
|
|
@@ -90,7 +94,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
90
94
|
requirements:
|
|
91
95
|
- - ">="
|
|
92
96
|
- !ruby/object:Gem::Version
|
|
93
|
-
version:
|
|
97
|
+
version: 2.7.8
|
|
94
98
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
95
99
|
requirements:
|
|
96
100
|
- - ">="
|