class Faraday::HttpCache::Storage
Faraday::HttpCache::Storage.new(:memory_store, serializer: Marshal)
# Creates a new Storage using Marshal for serialization.
Faraday::HttpCache::Storage.new(Rails.cache)
# Reuse some other instance of an ActiveSupport::Cache::Store object.
Faraday::HttpCache::Storage.new(:mem_cache_store)
# Creates a new Storage using a MemCached backend from ActiveSupport.
Examples
Internal: A wrapper around an ActiveSupport::CacheStore to store responses.
def assert_valid_store!
Raises an 'ArgumentError'.
expect API ('read' and 'write').
Internal: Checks if the given cache object supports the
def assert_valid_store! unless cache.respond_to?(:read) && cache.respond_to?(:write) && cache.respond_to?(:delete) raise ArgumentError.new("#{cache.inspect} is not a valid cache store as it does not responds to 'read', 'write' or 'delete'.") end end
def cache_key_for(url)
url - The request URL.
account the current serializer to avoid cross serialization issues.
Internal: Computes the cache key for a specific request, taking in
def cache_key_for(url) prefix = (@serializer.is_a?(Module) ? @serializer : @serializer.class).name Digest::SHA1.hexdigest("#{prefix}#{url}") end
def delete(url)
def delete(url) cache_key = cache_key_for(url) cache.delete(cache_key) end
def deserialize_entry(*objects)
def deserialize_entry(*objects) objects.map { |object| deserialize_object(object) } end
def deserialize_object(object)
def deserialize_object(object) @serializer.load(object).each_with_object({}) do |(key, value), hash| hash[key.to_sym] = value end end
def initialize(options = {})
:serializer - A serializer object that should
respond to 'read', 'write', and 'delete'.
:store - An cache store object that should
:logger - A Logger object to be used to emit warnings.
options - Storage options (default: {}).
Internal: Initialize a new Storage object with a cache backend.
def initialize(options = {}) @cache = options[:store] || MemoryStore.new @serializer = options[:serializer] || JSON @logger = options[:logger] assert_valid_store! end
def lookup_response(request, entries)
entries - An Array of pairs of Hashes (request, response).
request.
request - A Faraday::HttpCache::::Request instance of the incoming HTTP
the given request.
Internal: Retrieve a response Hash from the list of entries that match
def lookup_response(request, entries) if entries entries = entries.map { |entry| deserialize_entry(*entry) } _, response = entries.find { |req, res| response_matches?(request, req, res) } response end end
def read(request, klass = Faraday::HttpCache::Response)
klass - The Class to be instantiated with the stored response.
request.
request - A Faraday::HttpCache::::Request instance of the incoming HTTP
HTTP request.
Internal: Attempt to retrieve an stored response that suits the incoming
def read(request, klass = Faraday::HttpCache::Response) cache_key = cache_key_for(request.url) entries = cache.read(cache_key) response = lookup_response(request, entries) if response klass.new(response) end end
def response_matches?(request, cached_request, cached_response)
cached_response - The Hash of the response that was cached.
cached_request - The Hash of the request that was cached.
current HTTP request.
request - A Faraday::HttpCache::::Request instance of the
request.
Internal: Check if a cached response and request matches the given
def response_matches?(request, cached_request, cached_response) request.method.to_s == cached_request[:method].to_s && vary_matches?(cached_response, request, cached_request) end
def serialize_entry(*objects)
def serialize_entry(*objects) objects.map { |object| serialize_object(object) } end
def serialize_object(object)
def serialize_object(object) @serializer.dump(object) end
def vary_matches?(cached_response, request, cached_request)
def vary_matches?(cached_response, request, cached_request) headers = Faraday::Utils::Headers.new(cached_response[:response_headers]) vary = headers['Vary'].to_s vary.empty? || (vary != '*' && vary.split(/[\s,]+/).all? do |header| request.headers[header] == cached_request[:headers][header] end) end
def warn(message)
def warn(message) @logger.warn(message) if @logger end
def write(request, response)
response - The Faraday::HttpCache::Response instance to be stored.
request.
request - A Faraday::HttpCache::::Request instance of the executed HTTP
Internal: Store a response inside the cache.
def write(request, response) key = cache_key_for(request.url) entry = serialize_entry(request.serializable_hash, response.serializable_hash) entries = cache.read(key) || [] entries = entries.dup if entries.frozen? entries.reject! do |(cached_request, cached_response)| response_matches?(request, deserialize_object(cached_request), deserialize_object(cached_response)) end entries << entry cache.write(key, entries) rescue Encoding::UndefinedConversionError => e warn "Response could not be serialized: #{e.message}. Try using Marshal to serialize." raise e end