Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Rack::TryStatic middleware

- try match request to a static file
  • Loading branch information...
commit 07022018ff063c96b8b92151ad741f8abed58ebb 1 parent a8f77fb
gmarik gmarik authored
1  README.rdoc
View
@@ -47,6 +47,7 @@ interface:
* Rack::Access - Limits access based on IP address
* Rack::ResponseHeaders - Manipulates response headers object at runtime
* Rack::SimpleEndpoint - Creates simple endpoints with routing rules, similar to Sinatra actions
+* Rack::TryStatic - Tries to match request to a static file
=== Use
36 lib/rack/contrib/try_static.rb
View
@@ -0,0 +1,36 @@
+module Rack
+
+ # The Rack::TryStatic middleware delegates requests to Rack::Static middleware
+ # trying to match a static file
+ #
+ # Examples
+ #
+ # use Rack::TryStatic,
+ # :root => "public", # static files root dir
+ # :urls => %w[/], # match all requests
+ # :try => ['.html', 'index.html', '/index.html'] # try these postfixes sequentially
+ #
+ # uses same options as Rack::Static with extra :try option which is an array
+ # of postfixes to find desired file
+
+ class TryStatic
+
+ def initialize(app, options)
+ @app = app
+ @try = ['', *options.delete(:try)]
+ @static = ::Rack::Static.new(
+ lambda { [404, {}, []] },
+ options)
+ end
+
+ def call(env)
+ orig_path = env['PATH_INFO']
+ found = nil
+ @try.each do |path|
+ resp = @static.call(env.merge!({'PATH_INFO' => orig_path + path}))
+ break if 404 != resp[0] && found = resp
+ end
+ found or @app.call(env.merge!('PATH_INFO' => orig_path))
+ end
+ end
+end
1  test/documents/existing.html
View
@@ -0,0 +1 @@
+existing.html
1  test/documents/index.htm
View
@@ -0,0 +1 @@
+index.htm
1  test/documents/index.html
View
@@ -0,0 +1 @@
+index.html
44 test/spec_rack_try_static.rb
View
@@ -0,0 +1,44 @@
+require 'test/spec'
+
+require 'rack'
+require 'rack/contrib/try_static'
+require 'rack/mock'
+
+def request(options = {})
+ options.merge!({
+ :urls => %w[/],
+ :root => ::File.expand_path(::File.dirname(__FILE__)),
+ })
+
+ @request =
+ Rack::MockRequest.new(
+ Rack::TryStatic.new(
+ lambda {[200, {}, ["Hello World"]]},
+ options))
+end
+
+describe "Rack::TryStatic" do
+ context 'when file cannot be found' do
+ it 'should call call app' do
+ res = request(:try => ['html']).get('/documents')
+ res.should.be.ok
+ res.body.should == "Hello World"
+ end
+ end
+
+ context 'when file can be found' do
+ it 'should serve first found' do
+ res = request(:try => ['.html', '/index.html', '/index.htm']).get('/documents')
+ res.should.be.ok
+ res.body.strip.should == "index.html"
+ end
+ end
+
+ context 'when path_info maps directly to file' do
+ it 'should serve existing' do
+ res = request(:try => ['/index.html']).get('/documents/existing.html')
+ res.should.be.ok
+ res.body.strip.should == "existing.html"
+ end
+ end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.