Module: Philiprehberger::Etag

Defined in:
lib/philiprehberger/etag.rb,
lib/philiprehberger/etag/parser.rb,
lib/philiprehberger/etag/matcher.rb,
lib/philiprehberger/etag/version.rb,
lib/philiprehberger/etag/generator.rb,
lib/philiprehberger/etag/middleware.rb,
lib/philiprehberger/etag/conditional.rb

Defined Under Namespace

Modules: Conditional, Generator, Matcher, Parser Classes: Error, Middleware

Constant Summary collapse

VERSION =
'0.3.0'

Class Method Summary collapse

Class Method Details

.equal?(a, b) ⇒ Boolean

Compare two ETag strings using weak comparison semantics (W/ prefix is ignored).

Parameters:

  • a (String)

    first ETag string

  • b (String)

    second ETag string

Returns:

  • (Boolean)

    true if the two ETags represent the same validator



93
94
95
96
97
# File 'lib/philiprehberger/etag.rb', line 93

def self.equal?(a, b)
  return false if a.nil? || b.nil?

  a.sub(%r{\AW/}, '') == b.sub(%r{\AW/}, '')
end

.for_file(path, algorithm: :sha256) ⇒ String

Generates a strong ETag for a file based on its mtime and size. Does not read file content.

Parameters:

  • path (String)

    the file path

  • algorithm (Symbol) (defaults to: :sha256)

    the hash algorithm (:sha256, :sha512, :md5, :sha1)

Returns:

  • (String)

    a quoted ETag string

Raises:

  • (Errno::ENOENT)

    if the file does not exist

  • (ArgumentError)

    if the algorithm is not supported



67
68
69
# File 'lib/philiprehberger/etag.rb', line 67

def self.for_file(path, algorithm: :sha256)
  Generator.for_file(path, algorithm: algorithm)
end

.generate(content, algorithm: :sha256) ⇒ String

Generates a strong ETag from content using the specified algorithm.

Parameters:

  • content (String)

    the content to hash

  • algorithm (Symbol) (defaults to: :sha256)

    the hash algorithm (:sha256, :sha512, :md5, :sha1)

Returns:

  • (String)

    a quoted ETag string

Raises:

  • (ArgumentError)

    if the algorithm is not supported



20
21
22
# File 'lib/philiprehberger/etag.rb', line 20

def self.generate(content, algorithm: :sha256)
  Generator.strong(content, algorithm: algorithm)
end

.match?(etag, if_none_match_header) ⇒ Boolean

Evaluates an ETag against an If-None-Match header using weak comparison.

Parameters:

  • etag (String)

    the ETag to compare

  • if_none_match_header (String)

    the If-None-Match header value

Returns:

  • (Boolean)

    true if the ETag matches



37
38
39
# File 'lib/philiprehberger/etag.rb', line 37

def self.match?(etag, if_none_match_header)
  Matcher.match?(etag, if_none_match_header)
end

.modified?(etag, request_headers) ⇒ Boolean

Checks if a resource has been modified based on request headers.

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



55
56
57
# File 'lib/philiprehberger/etag.rb', line 55

def self.modified?(etag, request_headers)
  Matcher.modified?(etag, request_headers)
end

.modified_since?(last_modified, if_modified_since_header) ⇒ Boolean

Checks if a resource has been modified since the given If-Modified-Since header value.

Parameters:

  • last_modified (Time)

    the last modification time of the resource

  • if_modified_since_header (String)

    the If-Modified-Since header value (RFC 2822)

Returns:

  • (Boolean)

    true if the resource has been modified since the header date



84
85
86
# File 'lib/philiprehberger/etag.rb', line 84

def self.modified_since?(last_modified, if_modified_since_header)
  Conditional.modified_since?(last_modified, if_modified_since_header)
end

.not_modified_since?(last_modified, if_modified_since_header) ⇒ Boolean

Checks if a resource has NOT been modified since the given If-Modified-Since header value.

Parameters:

  • last_modified (Time)

    the last modification time of the resource

  • if_modified_since_header (String)

    the If-Modified-Since header value (RFC 2822)

Returns:

  • (Boolean)

    true if the resource has NOT been modified since the header date



104
105
106
# File 'lib/philiprehberger/etag.rb', line 104

def self.not_modified_since?(last_modified, if_modified_since_header)
  Conditional.not_modified_since?(last_modified, if_modified_since_header)
end

.parse(header) ⇒ Hash+

Parses an ETag header value into a structured hash or array of hashes.

Parameters:

  • header (String)

    the ETag header value

Returns:

  • (Hash, Array<Hash>)

    a hash with :weak and :value keys, or array of such hashes



75
76
77
# File 'lib/philiprehberger/etag.rb', line 75

def self.parse(header)
  Parser.parse(header)
end

.strong_match?(etag, if_match_header) ⇒ Boolean

Evaluates an ETag against an If-Match header using strong comparison.

Parameters:

  • etag (String)

    the ETag to compare

  • if_match_header (String)

    the If-Match header value

Returns:

  • (Boolean)

    true if the ETag strongly matches



46
47
48
# File 'lib/philiprehberger/etag.rb', line 46

def self.strong_match?(etag, if_match_header)
  Matcher.strong_match?(etag, if_match_header)
end

.weak(content) ⇒ String

Generates a weak ETag from content using MD5.

Parameters:

  • content (String)

    the content to hash

Returns:

  • (String)

    a weak ETag string prefixed with W/



28
29
30
# File 'lib/philiprehberger/etag.rb', line 28

def self.weak(content)
  Generator.weak(content)
end