Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add features, fix bugs

  • Loading branch information...
commit 080866ae3e607188d1e5feb6ed8362bae13ecf47 0 parents
@dolzenko authored
Showing with 85 additions and 0 deletions.
  1. +19 −0 README.md
  2. +66 −0 lib/rack/static_fallback.rb
19 README.md
@@ -0,0 +1,19 @@
+Bounces or redirects requests to missing static files.
+Partially inspired by 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 URL is redirected to options[: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
+
+To use with Rails add the following to your config/environments/development.rb:
+
+ config.middleware.insert_after(::Rack::Lock,
+ ::Rack::StaticFallback, :mode => :fallback,
+ :static_path_regex => %r{/public/uploads}
+ :fallback_static_url => "http://myproductionsite.com/")
66 lib/rack/static_fallback.rb
@@ -0,0 +1,66 @@
+module Rack
+ # Bounces or redirects requests to missing static files.
+ # Partially inspired by 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 URL is redirected to options[: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
+ #
+ # To use with Rails add the following to your config/environments/development.rb:
+ #
+ # config.middleware.insert_after(::Rack::Lock,
+ # ::Rack::StaticFallback, :mode => :fallback,
+ # :static_path_regex => %r{/public/uploads}
+ # :fallback_static_url => "http://myproductionsite.com/")
+ #
+
+ class StaticFallback
+ 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]
+ end
+
+ 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
+ if @fallback_static_url
+ # redirect request to the production server
+ [ 302, { "Location" => ::File.join(@fallback_static_url, env["PATH_INFO"]) }, [] ]
+ else
+ ActionController::Base.logger.debug "You're using StaticFallback middleware with StaticFallback.mode set to :fallback " <<
@edavis10
edavis10 added a note

Looks like this assumes the application is using ActionController (Rails). I think this would fail in a non-Rails application like Sinatra.

@dolzenko Owner
dolzenko added a note

Indeed that's lame of me to assume the hegemony of three letter framework, but what should I use instead env['rack.logger'] ?

@edavis10
edavis10 added a note

MemoryBloat lets you pass in a logger object which it writes to. What if you used something like this?

You could then give a default logger option of nil and only log if the logger is present:

def initialize
  @logger = options[:logger] || nil

def call
  @logger.debug "...." if @logger
@dolzenko Owner

um actually I think we don't need logger here since it looks like initialization error, check this out http://github.com/dolzenko/rack-static_fallback/commit/3a889faf221fc9f89f8a9f17e9a73fcc0537a99c

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ "however StaticFallback.fallback_static_url has not been set."
+ not_found
+ end
+ end
+
+ else
+ @app.call(env)
+ end
+ end
+
+ def not_found
+ [ 404, { "Content-Type" => "text/html", "Content-Length" => "0" }, [] ]
+ end
+ end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.