From e4ab2cc40bdbd1698f4bcf138e83c4823d118f81 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Fri, 25 Feb 2011 19:43:06 -0800 Subject: proxy +to_path+ calls in the response body We need to do this for apps that depend on things like the sendfile() optimizations in Rainbows! --- lib/raindrops/middleware.rb | 41 ++++++++++++++++++++++++++++------------- test/test_middleware.rb | 17 +++++++++++++++-- 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/lib/raindrops/middleware.rb b/lib/raindrops/middleware.rb index 79496fc..ea19ffc 100644 --- a/lib/raindrops/middleware.rb +++ b/lib/raindrops/middleware.rb @@ -31,29 +31,44 @@ class Raindrops::Middleware # standard Rack endpoint def call(env) - env[PATH_INFO] == @path ? stats_response : dup._call(env) - end + env[PATH_INFO] == @path and return stats_response - def _call(env) @stats.incr_calling - status, headers, @app = @app.call(env) + + status, headers, body = @app.call(env) + rv = [ status, headers, Proxy.new(body, @stats) ] # the Rack server will start writing headers soon after this method @stats.incr_writing - [ status, headers, self ] + rv ensure @stats.decr_calling end - # yield to the Rack server here for writing - def each - @app.each { |x| yield x } - end + class Proxy + def initialize(body, stats) + @body, @stats = body, stats + end + + # yield to the Rack server here for writing + def each + @body.each { |x| yield x } + end - # the Rack server should call this after #each (usually ensure-d) - def close - @stats.decr_writing - @app.close if @app.respond_to?(:close) + # the Rack server should call this after #each (usually ensure-d) + def close + @stats.decr_writing + @body.close if @body.respond_to?(:close) + end + + def to_path + @body.to_path + end + + def respond_to?(m) + m = m.to_sym + :close == m || @body.respond_to?(m) + end end def stats_response diff --git a/test/test_middleware.rb b/test/test_middleware.rb index e2fdc38..eedf04a 100644 --- a/test/test_middleware.rb +++ b/test/test_middleware.rb @@ -14,7 +14,7 @@ class TestMiddleware < Test::Unit::TestCase app = Raindrops::Middleware.new(@app) response = app.call({}) assert_equal @response[0,2], response[0,2] - assert response.last.kind_of?(Raindrops::Middleware) + assert response.last.kind_of?(Raindrops::Middleware::Proxy) assert response.last.object_id != app.object_id tmp = [] response.last.each { |y| tmp << y } @@ -35,7 +35,7 @@ class TestMiddleware < Test::Unit::TestCase assert_equal 0, stats.calling assert_equal 1, stats.writing assert_equal 200, response[0] - assert response.last.kind_of?(Raindrops::Middleware) + assert response.last.kind_of?(Raindrops::Middleware::Proxy) tmp = [] response.last.each do |y| assert_equal 1, stats.writing @@ -108,4 +108,17 @@ class TestMiddleware < Test::Unit::TestCase assert_equal expect, response end + def test_middleware_proxy_to_path_missing + app = Raindrops::Middleware.new(@app) + response = app.call({}) + body = response[2] + assert_kind_of Raindrops::Middleware::Proxy, body + assert ! body.respond_to?(:to_path) + assert body.respond_to?(:close) + orig_body = @response[2] + + def orig_body.to_path; "/dev/null"; end + assert body.respond_to?(:to_path) + assert_equal "/dev/null", body.to_path + end end -- cgit v1.2.3-24-ge0c7