Class: Rack::StaticFallback

Inherits:
Object
  • Object
show all
Defined in:
lib/rack/static_fallback.rb

Overview

Bounces or redirects requests to missing static files. Partially inspired by [menendez.com/blog/using-django-as-pass-through-image-proxy/](http://menendez.com/blog/using-django-as-pass-through-image-proxy/)

I.e. could be useful when you want to run the server with production database locally and have user uploaded content fetched transparently from production site.

Options:

:mode - [ :off,
          :bounce, # returns 404 to any request to static URL,
          :fallback ] # any request to static path is redirected to :fallback_static_url
:static_path_regex - Regexp which matches the path to your static files.
                     Along the lines of the Capistrano conventions defaults to `%r{/system/(audios|photos|videos)}`
:fallback_static_url - URL of the production site

Install via rubygems:

gem install rack-static_fallback

then, for Rails (any version which supports Rack) apps, add the following to your ‘config/environments/development.rb’

require 'rack/static_fallback'
config.middleware.insert_after ::Rack::Lock,
                               ::Rack::StaticFallback, :mode => :fallback,
                                                       :static_path_regex => %r{/system/uploads},
                                                       :fallback_static_url => "http://myproductionsite.com/"

Aternatively, you should also be able to use the gem in Rack apps with:

use ::Rack::StaticFallback, :mode => :fallback,
                            :static_path_regex => %r{/system/uploads},
                            :fallback_static_url => "http://myproductionsite.com/"

in your ‘config.ru’ (this is untested so mileage may vary)

Instance Method Summary collapse

Constructor Details

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

Returns a new instance of StaticFallback.



38
39
40
41
42
43
44
45
46
47
48
# File 'lib/rack/static_fallback.rb', line 38

def initialize(app, options = {})
  @app = app
  @mode = options[:mode] || :off
  # along the lines of the Capistrano defaults
  @static_path_regex = options[:static_path_regex] || %r{/system/(audios|photos|videos)}
  @fallback_static_url = options[:fallback_static_url]

  if @mode == :fallback && !@fallback_static_url
    raise ArgumentError, "Rack::StaticFallback :mode => :fallback option specified without :fallback_static_url option"
  end
end

Instance Method Details

#call(env) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/rack/static_fallback.rb', line 50

def call(env)
  if env["PATH_INFO"] =~ @static_path_regex
    # If we get here that means that underlying web server wasn't able to serve the static file,
    # i.e. it wasn't found.
    case @mode
      when :off
        # pass the request to next middleware, ultimately Rails
        @app.call(env)

      when :bounce
        # don't pass the request so that it doesn't hit framework, which
        # speeds up things significantly
        not_found

      when :fallback
        # redirect request to the production server
        [ 302, { "Location" => ::File.join(@fallback_static_url, env["PATH_INFO"]), "Content-Type" => "" }, [] ]
    end

  else
    @app.call(env)
  end
end

#not_foundObject



74
75
76
# File 'lib/rack/static_fallback.rb', line 74

def not_found
  [ 404, { "Content-Type" => "text/html", "Content-Length" => "0" }, [] ]
end