Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added digest_class configuration option #724

Merged
merged 1 commit into from May 27, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/active_support/cache/dalli_store.rb
Expand Up @@ -345,7 +345,7 @@ def namespaced_key(key, options)
namespace = options[:namespace] if options
prefix = namespace.is_a?(Proc) ? namespace.call : namespace
key = "#{prefix}:#{key}" if prefix
key = "#{key[0, 213]}:md5:#{::Digest::MD5.hexdigest(key)}" if key && key.size > 250
key = "#{key[0, 213]}:md5:#{@options[:digest_class].hexdigest(key)}" if key && key.size > 250
key
end
alias :normalize_key :namespaced_key
Expand Down
11 changes: 9 additions & 2 deletions lib/dalli/client.rb
Expand Up @@ -29,8 +29,10 @@ class Client
# - :serializer - defaults to Marshal
# - :compressor - defaults to zlib
# - :cache_nils - defaults to false, if true Dalli will not treat cached nil values as 'not found' for #fetch operations.
# - :digest_class - defaults to Digest::MD5, allows you to pass in an object that responds to the hexdigest method, useful for injecting a FIPS compliant hash object.
#
def initialize(servers=nil, options={})
options[:digest_class] = ::Digest::MD5 unless options[:digest_class]
@servers = normalize_servers(servers || ENV["MEMCACHE_SERVERS"] || '127.0.0.1:11211')
@options = normalize_options(options)
@ring = nil
Expand Down Expand Up @@ -351,7 +353,9 @@ def ring
server_options[:password] = uri.password
s = "#{uri.host}:#{uri.port}"
end
Dalli::Server.new(s, @options.merge(server_options))
options = @options.dup.merge(server_options)
options.delete(:digest_class)
Dalli::Server.new(s, options)
end, @options
)
end
Expand Down Expand Up @@ -379,7 +383,7 @@ def validate_key(key)
key = key_with_namespace(key)
if key.length > 250
max_length_before_namespace = 212 - (namespace || '').size
key = "#{key[0, max_length_before_namespace]}:md5:#{Digest::MD5.hexdigest(key)}"
key = "#{key[0, max_length_before_namespace]}:md5:#{@options[:digest_class].hexdigest(key)}"
end
return key
end
Expand Down Expand Up @@ -407,6 +411,9 @@ def normalize_options(opts)
rescue NoMethodError
raise ArgumentError, "cannot convert :expires_in => #{opts[:expires_in].inspect} to an integer"
end
unless opts[:digest_class].respond_to? :hexdigest
raise ArgumentError, "The digest_class object must respond to the hexdigest method"
end
opts
end

Expand Down
12 changes: 12 additions & 0 deletions test/test_active_support.rb
Expand Up @@ -2,6 +2,7 @@
# frozen_string_literal: true
require_relative 'helper'
require 'connection_pool'
require 'openssl'

class MockUser
def cache_key
Expand Down Expand Up @@ -50,6 +51,17 @@ def self.it_with_and_without_local_cache(message, &block)
with_cache :expires_in => 5.minutes, :frob => 'baz' do
assert_equal 'baz', @dalli.options[:frob]
end

with_cache :expires_in => 5.minutes, :digest_class => OpenSSL::Digest::SHA1 do
assert_equal OpenSSL::Digest::SHA1, @dalli.options[:digest_class]
end
end

it 'uses valid digest_class option' do
with_cache :expires_in => 5.minutes, :digest_class => OpenSSL::Digest::SHA1 do
dvalue = @dalli.fetch('a_key') { 123 }
assert_equal 123, dvalue
end
end

it_with_and_without_local_cache 'allow mute and silence' do
Expand Down
9 changes: 8 additions & 1 deletion test/test_dalli.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
require_relative 'helper'
require 'openssl'

describe 'Dalli' do
describe 'options parsing' do
Expand Down Expand Up @@ -33,6 +34,12 @@
assert_equal "wunderschoen", dc.send(:namespace)
dc.close
end

it 'raises error with invalid digest_class' do
assert_raises ArgumentError do
Dalli::Client.new('foo', {:expires_in => 10, :digest_class => Object })
end
end
end

describe 'key validation' do
Expand Down Expand Up @@ -529,7 +536,7 @@
dc.close
dc = nil

dc = Dalli::Client.new("localhost:#{port}")
dc = Dalli::Client.new("localhost:#{port}", :digest_class => ::OpenSSL::Digest::SHA1)

assert op_addset_succeeds(dc.set('456', 'xyz', 0, :raw => true))

Expand Down