PlugResponseCache

Hex.pm Hex.pm Travis

A highly-configurable plug to cache entire responses. The library allows you to configure if, how long and where a response will be cached.

Installation

The package can be installed by adding plug_response_cache to your list of dependencies in mix.exs:

def deps do
  [
    {:plug_response_cache, "~> 0.1.0"}
  ]
end

Usage

Below is a brief overview of PlugResponseCache’s usage. Full documentation is available on Hex.

Basic usage

After installing the :plug_response_cache library, add the PlugResponseCache plug to your pipeline as early as possible. Here’s what that looks like in a clean Phoenix installation:

pipeline :browser do
  plug(:accepts, ["html"])
  plug(PlugResponseCache)
  plug(:fetch_session)
  plug(:fetch_flash)
  plug(:protect_from_forgery)
  plug(:put_secure_browser_headers)
end

And that’s it! For basic usage at least. The default configuration will cache all successful GET requests in an ETS table, forever. If you need a different configuration, read on.

Configuration

The recommended way to configure the response cache is through your application’s configuration. Since all keys have a default, you only need to specify the ones you want to override.

config :plug_response_cache,
  enabled: false,
  store: MyApp.ResponseCache.MyCustomStore
  profile: MyApp.ResponseCache.MyCustomProfile

Since every option has a default, the response cache will also work without specifying any custom configuration.

It’s also possible to pass options to the plug. This is useful for enabling or disabling the response cache on the fly, or for toggling the debug mode.

pipeline :browser do
  # ...
  plug(PlugResponseCache, debug: true)
  # ...
end

Profiles

Profiles are the heart of PlugResponseCache’s configurability. They determine if and how long a response should be cached. The default profile caches all succesfull GET requests for a configurable amount of minutes. For a full example implementation, take a look at the PlugResponseCache.Profiles.Default module.

With cache_request? you can choose whether or not to pass the request through the response cache. If true, the response will be retrieved from the cache, or stored if nothing’s there yet. In the following example we’ll set up our profile to only cache GET requests.

defmodule MyCacheProfile do
  @behaviour PlugResponseCache.Profile

  alias Plug.Conn

  def cache_request?(%Conn{method: "GET"}, _opts), do: true
  def cache_request?(_conn, _opts), do: false

  # ...
end

The cache_request? callback probably the most interesting one to override. For example if you’d only want to cache a specific section of your application based on the url or on user authentication.

With cache_response? you can choose whether or not to cache a response before it’s sent. Here we’ll only cache the response if it was successful.

defmodule MyCacheProfile do
  @behaviour PlugResponseCache.Profile

  alias Plug.Conn

  # ...

  def cache_response?(%Conn{status: status}, _opts), do: status < 400
  def cache_response?(_conn, _opts), do: true
end

With expires we can determine at what time the cached response will expire. If you the response to be cached forever, you can return a :never atom. The default profile accepts an expire_time option set in minutes.

defmodule MyCacheProfile do
  @behaviour PlugResponseCache.Profile

  alias Plug.Conn

  # ...

  def expires(_conn, %{expiration_time: expiration_time}),
    do: :os.system_time(:seconds) + expiration_time * 60

  def expires(_conn, _opts), do: :never
end

The application configuration is also passed to the cache profile, so if a profile has options simply add them to the list. For example, the default profile (PlugResponseCache.Profiles.Default) has an expiration_time option to determine for how many minutes the response should be cached.

config :plug_response_cache,
  expiration_time: 5

Refer to the Profile behaviour’s documentation for a more thorough explanation of the various callbacks.

Stores

Stores determine where a response should be cached. By default, responses are stored in an ETS table.

For a full example implementation, take a look at the PlugResponseCache.Stores.Ets module.

Refer to the Store behaviour’s documentation for a more thorough explanation of the various callbacks.

Changelog

Please see CHANGELOG for more information what has changed recently.

Testing

$ mix test

Contributing

Pull requests are welcome!

Credits

This package is based on the Laravel (PHP) response cache package by Spatie.

Alternative libraries

There are two similar Elixir libraries I know of:

License

The MIT License (MIT). Please check the LICENSE for more information.