Class: Philiprehberger::Etag::Matcher
- Inherits:
-
Object
- Object
- Philiprehberger::Etag::Matcher
- Defined in:
- lib/philiprehberger/etag/matcher.rb
Overview
Evaluates If-None-Match and If-Match headers against ETags.
Can be used as a module (class methods) or instantiated with a header to expose the strong/weak predicate helpers.
Class Method Summary collapse
-
.match?(etag, header) ⇒ Boolean
Performs a weak comparison of an ETag against an If-None-Match header value.
-
.modified?(etag, request_headers) ⇒ Boolean
Determines whether a resource has been modified based on request headers.
-
.strong_match?(etag, header) ⇒ Boolean
Performs a strong comparison of an ETag against an If-Match header value.
Instance Method Summary collapse
-
#initialize(header) ⇒ Matcher
constructor
Builds a Matcher bound to a header value.
-
#strong_match?(etag) ⇒ Boolean
Returns true iff any entry in the header is a strong match for the given ETag.
-
#weak_match?(etag) ⇒ Boolean
Returns true iff any entry in the header has the same opaque-tag as the given ETag, ignoring weakness on either side.
Constructor Details
#initialize(header) ⇒ Matcher
Builds a Matcher bound to a header value. Instances expose #strong_match? and #weak_match? predicate helpers for distinguishing the nature of a match per RFC 7232 §2.3.2.
85 86 87 88 89 |
# File 'lib/philiprehberger/etag/matcher.rb', line 85 def initialize(header) @header = header @wildcard = !header.nil? && header.strip == '*' @entries = parse_entries(header) end |
Class Method Details
.match?(etag, header) ⇒ Boolean
Performs a weak comparison of an ETag against an If-None-Match header value. Weak comparison ignores the W/ prefix when comparing.
18 19 20 21 22 23 24 |
# File 'lib/philiprehberger/etag/matcher.rb', line 18 def self.match?(etag, header) return false if header.nil? || header.empty? return true if header.strip == '*' normalized = strip_weak(etag) (header).any? { |candidate| strip_weak(candidate) == normalized } end |
.modified?(etag, request_headers) ⇒ Boolean
Determines whether a resource has been modified based on request headers. Checks the If-None-Match header using weak comparison.
47 48 49 50 51 52 |
# File 'lib/philiprehberger/etag/matcher.rb', line 47 def self.modified?(etag, request_headers) if_none_match = request_headers['HTTP_IF_NONE_MATCH'] || request_headers['If-None-Match'] return true if if_none_match.nil? || if_none_match.empty? !match?(etag, if_none_match) end |
.strong_match?(etag, header) ⇒ Boolean
Performs a strong comparison of an ETag against an If-Match header value. Strong comparison requires exact match including the W/ prefix. Weak ETags never match in strong comparison.
33 34 35 36 37 38 39 |
# File 'lib/philiprehberger/etag/matcher.rb', line 33 def self.strong_match?(etag, header) return false if header.nil? || header.empty? return false if weak?(etag) return true if header.strip == '*' (header).any? { |candidate| !weak?(candidate) && candidate == etag } end |
Instance Method Details
#strong_match?(etag) ⇒ Boolean
Returns true iff any entry in the header is a strong match for the given ETag. Strong comparison requires that the opaque-tag be byte-for-byte equal and that neither side be weak.
Wildcard ‘*` returns true for both predicates — wildcard expresses “any representation” per RFC 7232 §3.1 and is not a weakness signal.
100 101 102 103 104 105 106 107 108 |
# File 'lib/philiprehberger/etag/matcher.rb', line 100 def strong_match?(etag) return false if etag.nil? return true if @wildcard # wildcard matches any representation parsed = parse_one(etag) return false if parsed[:weak] @entries.any? { |entry| !entry[:weak] && entry[:value] == parsed[:value] } end |
#weak_match?(etag) ⇒ Boolean
Returns true iff any entry in the header has the same opaque-tag as the given ETag, ignoring weakness on either side. This is the weak comparison function per RFC 7232 §2.3.2.
Wildcard ‘*` returns true for both predicates.
118 119 120 121 122 123 124 |
# File 'lib/philiprehberger/etag/matcher.rb', line 118 def weak_match?(etag) return false if etag.nil? return true if @wildcard # wildcard matches any representation parsed = parse_one(etag) @entries.any? { |entry| entry[:value] == parsed[:value] } end |