diff --git a/README.md b/README.md index 973a31d..6145ed7 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,10 @@ Refraction can be installed in a Rails application as a plugin. $ script/plugin install git://github.com/pivotal/refraction.git +It can also be used as a gem: + + $ gem install refraction + In `environments/production.rb`, add Refraction at or near the top of your middleware stack. config.middleware.insert_before(::Rack::Lock, ::Refraction, {}) @@ -102,6 +106,17 @@ The `found!` method tells Refraction to return a response with a `302 Found` sta URL for the Location header. Like `#rewrite!` it can take either a string or hash argument to set the URL or some of its components. +### `RequestContext#respond!(status, headers, content)` + +Use `respond!` to return an arbitrary response to the request. This is useful for responding with +the contents of a static file. For example: + + req.respond!(503, {'Content-Type' => 'text/html'}, File.read(MAINTENANCE_PATH)) + +The args are largely the same as the contents of a standard Rack response array with the exceptions +that you don't need to wrap the content in an array, and the Content-Length header is generated so it +should not be supplied. + ### URL components The request object provides the following components of the URL for matching requests: `scheme`, diff --git a/lib/refraction.rb b/lib/refraction.rb index 6384a69..38f17d6 100644 --- a/lib/refraction.rb +++ b/lib/refraction.rb @@ -26,12 +26,9 @@ def initialize(env) end def response - headers = { - 'Location' => location, - 'Content-Type' => 'text/plain', - 'Content-Length' => message.length.to_s - } - [status, headers, message] + headers = @headers || { 'Location' => location, 'Content-Type' => 'text/plain' } + headers['Content-Length'] = message.length.to_s + [status, headers, [message]] end # URI part accessors @@ -95,6 +92,13 @@ def found!(options) @message = "moved to #{@uri}" end + def respond!(status, headers, content) + @action = :respond + @status = status + @headers = headers + @message = content + end + def location @uri.to_s end @@ -124,7 +128,7 @@ def call(env) self.rules.call(context) case context.action - when :permanent, :found + when :permanent, :found, :respond context.response when :rewrite env["rack.url_scheme"] = context.scheme diff --git a/spec/refraction_spec.rb b/spec/refraction_spec.rb index a9d61c3..e18cf9f 100644 --- a/spec/refraction_spec.rb +++ b/spec/refraction_spec.rb @@ -173,6 +173,24 @@ end end + describe "generate arbitrary response" do + before(:each) do + Refraction.configure do |req| + req.respond!(503, {'Content-Type' => 'text/plain'}, "Site down for maintenance.") + end + end + + it "should respond with status, headers and content" do + env = Rack::MockRequest.env_for('http://example.com', :method => 'get') + app = mock('app') + response = Refraction.new(app).call(env) + response[0].should == 503 + response[1]['Content-Length'].to_i.should == "Site down for maintenance.".length + response[1]['Content-Type'].should == "text/plain" + response[2].should == ["Site down for maintenance."] + end + end + describe "environment" do before(:each) do Refraction.configure do |req|