Module: Philiprehberger::Etag::Generator

Defined in:
lib/philiprehberger/etag/generator.rb

Overview

Generates strong and weak ETags from content using cryptographic hashes.

Constant Summary collapse

ALGORITHMS =
{
  sha256: Digest::SHA256,
  sha512: Digest::SHA512,
  md5: Digest::MD5,
  sha1: Digest::SHA1
}.freeze
OPENSSL_ALGORITHMS =

Algorithms that delegate to OpenSSL::Digest rather than the stdlib ‘digest/*` classes.

{ sha3_256: 'SHA3-256' }.freeze

Class Method Summary collapse

Class Method Details

.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, :sha3_256)

Returns:

  • (String)

    a quoted ETag string

Raises:

  • (Errno::ENOENT)

    if the file does not exist

  • (ArgumentError)

    if the algorithm is not supported



48
49
50
51
52
53
# File 'lib/philiprehberger/etag/generator.rb', line 48

def self.for_file(path, algorithm: :sha256)
  stat = File.stat(path)
  fingerprint = "#{stat.mtime.to_i}-#{stat.size}"
  digest = compute_digest(fingerprint, algorithm)
  %("#{digest}")
end

.strong(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, :sha3_256)

Returns:

  • (String)

    a quoted ETag string, e.g. ‘“"a1b2c3…"”`

Raises:

  • (ArgumentError)

    if the algorithm is not supported



26
27
28
29
# File 'lib/philiprehberger/etag/generator.rb', line 26

def self.strong(content, algorithm: :sha256)
  digest = compute_digest(content, algorithm)
  %("#{digest}")
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, e.g. ‘“W/"a1b2c3…"”`



35
36
37
38
# File 'lib/philiprehberger/etag/generator.rb', line 35

def self.weak(content)
  digest = Digest::MD5.hexdigest(content.to_s)
  %(W/"#{digest}")
end