mattiasottosson / rack-cache-heroku-cedar-example

Basic example for using HTTP-cache on Heroku with Rack:cache and Memcached
http://rack-cache-example.herokuapp.com/
5 stars 0 forks source link

== Rack Cache Example

This is a example app to demonstrate how to use http-caching with Rack:Cache and Memcached on the Heroku Cedar stack

For more information on http-caching, take a look Ryan Bates screencast #321: http://railscasts.com/episodes/321-http-caching and this blog post from Ryan Tomayko: http://tomayko.com/writings/things-caches-do

Example app on Heorku: http://bit.ly/Ab7fsl

== Instructions

  1. Add the dalli and rack-cache gem to the Gemfile: gem 'dalli' gem 'rack-cache'

  2. Tell cache_store in production.rb to use dalli and config midleware from the Heroku env.: In production.rb:

    Use a different cache store in production

    config.cache_store = :mem_cache_store

    config.cache_store = :dalli_store config.middleware.use Rack::Cache, :verbose => true, :metastore => "memcached://#{ENV['MEMCACHE_SERVERS']}", :entitystore => "memcached://#{ENV['MEMCACHE_SERVERS']}"

  3. Generate etag and set expires_in your controller action. In this static example I generate the etag based on the last modified date on the index page template:

    def index last_modified = File.mtime("#{Rails.root}/app/views/pages/index.html.erb") fresh_when last_modified: last_modified , public: true, etag: last_modified expires_in 10.seconds, public: true end

  4. Add Memcached to your Heroku app.

  5. Verify that Rack:Cache gets loaded by running heroku run rake middleware:

    rack-cache-example (master)$ heroku run rake middleware Running rake middleware attached to terminal... up, run.1 use Rack::Cache use ActionDispatch::Static use Rack::Lock use # use Rack::Runtime use Rack::MethodOverride use ActionDispatch::RequestId use Rails::Rack::Logger use ActionDispatch::ShowExceptions use ActionDispatch::DebugExceptions use ActionDispatch::RemoteIp use ActionDispatch::Callbacks use ActiveRecord::ConnectionAdapters::ConnectionManagement use ActiveRecord::QueryCache use ActionDispatch::Cookies use ActionDispatch::Session::CookieStore use ActionDispatch::Flash use ActionDispatch::ParamsParser use ActionDispatch::Head use Rack::ConditionalGet use Rack::ETag use ActionDispatch::BestStandardsSupport use Rack::Cache run RackCacheExample::Application.routes

  6. Verify your setup with heroku logs and curl:

    rack-cache-example (master)$ heroku logs 2012-03-01T17:31:36+00:00 app[web.1]: cache: [HEAD /] fresh 2012-03-01T17:31:36+00:00 heroku[router]: HEAD rack-cache-example.herokuapp.com/ dyno=web.1 queue=0 wait=0ms service=9ms status=200 bytes=0

    rack-cache-example (master)$ curl -I http://rack-cache-example.herokuapp.com/ HTTP/1.1 200 OK Age: 2 Cache-Control: max-age=10, public Content-length: 1429 Content-Type: text/html; charset=utf-8 Date: Thu, 01 Mar 2012 17:32:55 GMT Etag: "eb288d4e68e81d141653d5575d682012" Last-Modified: Thu, 01 Mar 2012 17:05:12 GMT

  7. When passing in the etag as If-None-Match-header you should see a 304 - not modified response:

    rack-cache-example (master)$ curl -I http://rack-cache-example.herokuapp.com/ --header 'If-None-Match: "eb288d4e68e81d141653d5575d682012"' HTTP/1.1 304 Not Modified Age: 4 Cache-Control: max-age=10, public Date: Thu, 01 Mar 2012 17:35:23 GMT Etag: "eb288d4e68e81d141653d5575d682012" Server: WEBrick/1.3.1 (Ruby/1.9.2/2011-07-09)

  8. Voila!