tina4ruby 3.13.108 → 3.13.109

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: c940eabf57b7ba299db01f414b5d24d949af99cf970d49fa677e69f77b9192c9
4
- data.tar.gz: 83fb893d4db991b8393f22e727d3b7b9e220553f9118eb8a8a52a176dbea390b
3
+ metadata.gz: 88f7a221999f8c02e97a6e49f5002065f85dce2605f0bb26ccf05749667c44a0
4
+ data.tar.gz: a62e0e3746c4f0e8e2d1b01269c72fd93c2f89885c051c9642086a3074d901f9
5
5
  SHA512:
6
- metadata.gz: 7a04a51dbdd80fb05f7213c3983a03e5bf351eebf8ad5ef197e8e80c6489e47ace86a0417131cc2d3a8bbca6554c42dc96016f66c098cc103a5c4f411980137f
7
- data.tar.gz: f4e952bb42149b90c62b4bba12695c02234fdf11c19f30bb0744031190144bc0b02c13c7d55916ac1bc9c18f130e66a504e071383ac221413a3b7980e2d1f5ac
6
+ metadata.gz: 750fbc4f76f70bf58b2290a60ba9bc120f51fba91869c7b225bb326ce19b9d08e1a682c7a6aba8c9ddbc441acc0179daffe0493d49f3680761a92146ff621398
7
+ data.tar.gz: f5e2eb88d2c544c2d549f09fd6f2fb060866b452d45a7cb2db01c10da73e0829d65b9ad7daba092f9d5881cf5ac05bdc52067512a0d00d31fcd544376d54746d
@@ -454,6 +454,28 @@ module Tina4
454
454
  raw.split(",").map { |f| f.strip.downcase }.reject(&:empty?)
455
455
  end
456
456
 
457
+ # The Cache-Control directive NAMES on a request or response, lowercased.
458
+ #
459
+ # Parsed as comma-separated tokens with any `=value` stripped, rather than by
460
+ # substring search, so `no-cache="Set-Cookie"` is recognised as `no-cache`
461
+ # and a directive name never matches as a fragment of a longer one.
462
+ #
463
+ # @param carrier [Object, nil]
464
+ # @return [Array<String>]
465
+ def cache_control_tokens(carrier)
466
+ raw = header_value(carrier, "Cache-Control").to_s
467
+ raw.split(",").map { |token| token.split("=", 2).first.to_s.strip.downcase }.reject(&:empty?)
468
+ end
469
+
470
+ # Does the response carry a directive that lets a SHARED cache store it?
471
+ # (public / s-maxage / must-revalidate — RFC 9111 s3.5.)
472
+ #
473
+ # @param response [Object, nil]
474
+ # @return [Boolean]
475
+ def shared_cache_allowed?(response)
476
+ !(cache_control_tokens(response) & SHARED_CACHE_DIRECTIVES).empty?
477
+ end
478
+
457
479
  # May a SHARED cache store this response? (RFC 9111 s3, s4.1)
458
480
  #
459
481
  # s3 -- "if the cache is shared: the Authorization header field is not
@@ -464,15 +486,33 @@ module Tina4
464
486
  # s4.1 -- a stored response whose Vary contains "*" "always fails to
465
487
  # match", so storing one is pointless.
466
488
  #
489
+ # The same s3 reasoning covers two cases the Authorization check alone does
490
+ # not:
491
+ #
492
+ # - `no-store` forbids storage in any cache and `private` forbids it in a
493
+ # shared one (`no-cache` too, without revalidation) -- so a handler can
494
+ # keep a response out of this cache with the standard header.
495
+ # - A caller identified by a session Cookie is as specific as one carrying
496
+ # Authorization, and Tina4's own session mechanism IS a cookie. Because
497
+ # the key is method + URL, storing such a response replays one signed-in
498
+ # user's page to whoever asks for that URL next; a response that installs
499
+ # a session (Set-Cookie) is per-user by construction for the same reason.
500
+ #
501
+ # Both cookie cases stay cacheable when the response opts in explicitly with
502
+ # a shared-cache directive, which is how a genuinely public page served to
503
+ # cookie-bearing browsers keeps its hit rate.
504
+ #
467
505
  # @param request [Object, nil]
468
506
  # @param response [Object, nil]
469
507
  # @return [Boolean]
470
508
  def may_store?(request, response)
471
509
  return false if vary_fields(response).include?("*")
472
- return true if header_value(request, "Authorization").nil?
510
+ return false unless (cache_control_tokens(response) & %w[no-store private no-cache]).empty?
511
+ return shared_cache_allowed?(response) unless header_value(request, "Authorization").nil?
512
+ return shared_cache_allowed?(response) unless header_value(request, "Cookie").nil?
513
+ return shared_cache_allowed?(response) unless header_value(response, "Set-Cookie").nil?
473
514
 
474
- cache_control = header_value(response, "Cache-Control").to_s.downcase
475
- SHARED_CACHE_DIRECTIVES.any? { |directive| cache_control.include?(directive) }
515
+ true
476
516
  end
477
517
 
478
518
  # Do the nominated request headers match the ones recorded on the entry?
data/lib/tina4/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Tina4
4
- VERSION = "3.13.108"
4
+ VERSION = "3.13.109"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tina4ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.13.108
4
+ version: 3.13.109
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tina4 Team