Skip to content

Instantly share code, notes, and snippets.

@PetrKaleta
Created March 20, 2012 14:27
Show Gist options
  • Save PetrKaleta/2136160 to your computer and use it in GitHub Desktop.
Save PetrKaleta/2136160 to your computer and use it in GitHub Desktop.
The Rack::TryStatic middleware delegates requests to Rack::Static middleware trying to match a static file
# config.ru
# The Rack::TryStatic middleware delegates requests to Rack::Static middleware
# trying to match a static file
#
# Inspired by original code from rack-contrib
# http://github.com/rack/rack-contrib/blob/master/lib/rack/contrib/try_static.rb
#
module Rack
class TryStatic
def initialize(app, options)
@app = app
@try = ['', *options.delete(:try)]
@static = ::Rack::Static.new(lambda { [404, {}, []] }, options)
end
def call(env)
# make your life easier
req = ::Rack::Request.new env
valid_response = nil
# try to load file from its original path or including suffix
@try.each do |suffix|
response = @static.call(env.merge('PATH_INFO' => req.path_info + suffix))
# try it until there's a valid response
break if response[0] != 404 && valid_response = response
end
if !valid_response && # there's no valid response
req.get? && # it's a GET request
!req.referer && # there's no referer
!req.path_info.end_with?('/') && # it's not a DIR path
req.query_string.empty? && # there's no query string
::File.extname(req.path_info).empty? # it's not a link to some file
# actual file path is wrong, and it looks like a DIR path, so redirect it
valid_response = [301, { 'Location' => ::File.join(req.url, '/') }, []]
end
valid_response or @app.call(env)
end
end
end
use Rack::TryStatic, :root => 'public', :urls => %w[/], :try => ['index.html']
# run your own Rack app here or use this one to serve 404 messages:
run lambda { |env| [404, { 'Content-Type' => 'text/html' }, ['404 - page not found']] }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment