Class: Philiprehberger::Etag::Matcher

Inherits:
Object
  • Object
show all
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

Instance Method Summary collapse

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.

Parameters:

  • header (String, nil)

    the If-Match or If-None-Match header value



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.

Parameters:

  • etag (String)

    the ETag to compare

  • header (String)

    the If-None-Match header value (may contain multiple ETags)

Returns:

  • (Boolean)

    true if the ETag matches any value in the header



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)
  parse_etags(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.

Parameters:

  • etag (String)

    the current ETag of the resource

  • request_headers (Hash)

    a hash of request headers

Returns:

  • (Boolean)

    true if the resource has been modified (ETag does not match)



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.

Parameters:

  • etag (String)

    the ETag to compare

  • header (String)

    the If-Match header value (may contain multiple ETags)

Returns:

  • (Boolean)

    true if the ETag strongly matches any value in the header



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 == '*'

  parse_etags(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.

Parameters:

  • etag (String)

    the ETag to compare; accepts raw, quoted, or W/“…” input

Returns:

  • (Boolean)


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.

Parameters:

  • etag (String)

    the ETag to compare; accepts raw, quoted, or W/“…” input

Returns:

  • (Boolean)


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