Class: Faraday::HttpCache

Inherits:
Middleware
  • Object
show all
Defined in:
lib/faraday/http_cache.rb,
lib/faraday/http_cache/request.rb,
lib/faraday/http_cache/storage.rb,
lib/faraday/http_cache/response.rb,
lib/faraday/http_cache/cache_control.rb

Overview

Public: The middleware responsible for caching and serving responses. The middleware use the provided configuration options to establish a ‘Faraday::HttpCache::Storage’ to cache responses retrieved by the stack adapter. If a stored response can be served again for a subsequent request, the middleware will return the response instead of issuing a new request to it’s server. This middleware should be the last attached handler to your stack, so it will be closest to the inner app, avoiding issues with other middlewares on your stack.

Examples:

# Using the middleware with a simple client:
client = Faraday.new do |builder|
  builder.user :http_cache, store: my_store_backend
  builder.adapter Faraday.default_adapter
end

# Attach a Logger to the middleware.
client = Faraday.new do |builder|
  builder.use :http_cache, logger: my_logger_instance, store: my_store_backend
  builder.adapter Faraday.default_adapter
end

# Provide an existing CacheStore (for instance, from a Rails app)
client = Faraday.new do |builder|
  builder.use :http_cache, store: Rails.cache
end

# Use Marshal for serialization
client = Faraday.new do |builder|
  builder.use :http_cache, store: Rails.cache, serializer: Marshal
end

# Instrument events using ActiveSupport::Notifications
client = Faraday.new do |builder|
  builder.use :http_cache, store: Rails.cache, instrumenter: ActiveSupport::Notifications
end

Defined Under Namespace

Classes: CacheControl, MemoryStore, Request, Response, Storage

Constant Summary collapse

VALID_OPTIONS =

Internal: valid options for the ‘initialize’ configuration Hash.

[:store, :serializer, :logger, :shared_cache, :instrumenter, :instrument_name].freeze
UNSAFE_METHODS =
[:post, :put, :delete, :patch].freeze
ERROR_STATUSES =
(400..499).freeze
EVENT_NAME =

The name of the instrumentation event.

'http_cache.faraday'.freeze
CACHE_STATUSES =
[
  # The request was not cacheable.
  :unacceptable,

  # The response was cached and can still be used.
  :fresh,

  # The response was cached and the server has validated it with a 304 response.
  :valid,

  # The response was cache but was revalidated by the sserver.
  :invalid,

  # No response was found in the cache.
  :miss,

  # The response can't be cached.
  :uncacheable,

  # The request decided to ignore the cache.
  :bypass
].freeze

Instance Method Summary collapse

Constructor Details

#initialize(app, options = {}) ⇒ HttpCache

Public: Initializes a new HttpCache middleware.

app - the next endpoint on the ‘Faraday’ stack. args - aditional options to setup the logger and the storage.

:logger          - A logger object.
:serializer      - A serializer that should respond to 'dump' and 'load'.
:shared_cache    - A flag to mark the middleware as a shared cache or not.
:store           - A cache store that should respond to 'read', 'write', and 'delete'.
:instrumenter    - An instrumentation object that should respond to 'instrument'.
:instrument_name - The String name of the instrument being reported on (optional).

Examples:

# Initialize the middleware with a logger.
Faraday::HttpCache.new(app, logger: my_logger)

# Initialize the middleware with a logger and Marshal as a serializer
Faraday:HttpCache.new(app, logger: my_logger, serializer: Marshal)

# Initialize the middleware with a FileStore at the 'tmp' dir.
store = ActiveSupport::Cache.lookup_store(:file_store, ['tmp'])
Faraday::HttpCache.new(app, store: store)

# Initialize the middleware with a MemoryStore and logger
store = ActiveSupport::Cache.lookup_store
Faraday::HttpCache.new(app, store: store, logger: my_logger)


105
106
107
108
109
110
111
112
113
114
# File 'lib/faraday/http_cache.rb', line 105

def initialize(app, options = {})
  super(app)
  assert_valid_options!(options)

  @logger = options[:logger]
  @shared_cache = options.fetch(:shared_cache, true)
  @instrumenter = options[:instrumenter]
  @instrument_name = options.fetch(:instrument_name, EVENT_NAME)
  @storage = create_storage(options)
end

Instance Method Details

#call(env) ⇒ Object

Public: Process the request into a duplicate of this instance to ensure that the internal state is preserved.



118
119
120
# File 'lib/faraday/http_cache.rb', line 118

def call(env)
  dup.call!(env)
end

#call!(env) ⇒ Object

Internal: Process the stack request to try to serve a cache response. On a cacheable request, the middleware will attempt to locate a valid stored response to serve. On a cache miss, the middleware will forward the request and try to store the response for future requests. If the request can’t be cached, the request will be delegated directly to the underlying app and does nothing to the response. The processed steps will be recorded to be logged once the whole process is finished.

Returns a ‘Faraday::Response’ instance.



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/faraday/http_cache.rb', line 132

def call!(env)
  @trace = []
  @request = create_request(env)

  response = nil

  if @request.cacheable?
    response = if @request.no_cache?
      trace :bypass
      @app.call(env).on_complete do |fresh_env|
        response = Response.new(create_response(fresh_env))
        store(response)
      end
    else
      process(env)
    end
  else
    trace :unacceptable
    response = @app.call(env)
  end

  response.on_complete do
    delete(@request, response) if should_delete?(response.status, @request.method)
    log_request
    response.env[:http_cache_trace] = @trace
    instrument(response.env)
  end
end