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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fa6bc0e683d74abea34d8a3abc2d7746455a312845e902a4f7c1bcec7ecb98f7
4
- data.tar.gz: b71a9e04a9d13813d4ef142f0c76d54305e7107e7a44e42829b7572112763987
3
+ metadata.gz: fbd32a2e65add5d5f0e143fb98a411b78c5926e97cd56f5bc6d5ea0976ab4fee
4
+ data.tar.gz: 36af9ade2e7efc5a564f8e243f900998e5b77c48b8b71472b1753c0ea6f9100f
5
5
  SHA512:
6
- metadata.gz: d376e2451a706eea91c6a3ce7951c04ca2d36f4c5b36e7c725bc481d6d34d1fc7ac65969ff558a1854102979ac39e8feec143c94ad2b6b86bff3cbfdb520c240
7
- data.tar.gz: 104b4daca715a68d1706e3fa264594fee61cb88469910e03c6a59348fcce93b58d7546c38974d2df18a1276a4228ef3ad89d47cc0b3c8d09347858bbb1841eb2
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
- @route.cache_expires = time
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
- @route.cache_key = name || block
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.before_filters do
101
- next unless settings.caching?
102
- if (cached_response = load_cached_response)
103
- content_type cached_response[:content_type]
104
- halt 200, cached_response[:body]
105
- end
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
 
@@ -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 = 'http://www.padrinorb.com'
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']
@@ -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.0
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-10-31 00:00:00.000000000 Z
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.0
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.0
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.0
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.0
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: http://www.padrinorb.com
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: '0'
97
+ version: 2.7.8
94
98
  required_rubygems_version: !ruby/object:Gem::Requirement
95
99
  requirements:
96
100
  - - ">="