diff options
author | Yehuda Katz + Carl Lerche <ykatz+clerche@engineyard.com> | 2009-08-25 12:14:31 -0700 |
---|---|---|
committer | Yehuda Katz + Carl Lerche <ykatz+clerche@engineyard.com> | 2009-08-25 12:14:31 -0700 |
commit | c7ba911a43e513bd1adbee93f16d2b8efea7cc88 (patch) | |
tree | 0a3f88da172575fb9d85980975cbbe41ed6bd53c /actionpack | |
parent | 09fde6440a729e169e51c04f7caf0d19fe949c1d (diff) | |
download | rails-c7ba911a43e513bd1adbee93f16d2b8efea7cc88.tar.gz rails-c7ba911a43e513bd1adbee93f16d2b8efea7cc88.tar.bz2 rails-c7ba911a43e513bd1adbee93f16d2b8efea7cc88.zip |
ActionController::Metal can be a middleware
Diffstat (limited to 'actionpack')
-rw-r--r-- | actionpack/lib/action_controller/metal.rb | 40 | ||||
-rw-r--r-- | actionpack/lib/action_controller/metal/rack_convenience.rb | 8 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/http/response.rb | 5 | ||||
-rw-r--r-- | actionpack/test/new_base/metal_test.rb | 45 |
4 files changed, 85 insertions, 13 deletions
diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb index 5333ca497c..aad9570237 100644 --- a/actionpack/lib/action_controller/metal.rb +++ b/actionpack/lib/action_controller/metal.rb @@ -47,7 +47,7 @@ module ActionController # and response object available. You might wish to control the # environment and response manually for performance reasons. - attr_internal :status, :headers, :content_type + attr_internal :status, :headers, :content_type, :app, :response def initialize(*) @_headers = {} @@ -75,7 +75,34 @@ module ActionController # :api: private def to_a - [status, headers, response_body] + response ? response.to_a : [status, headers, response_body] + end + + class ActionEndpoint + def initialize(controller, action) + @controller, @action = controller, action + end + + def call(env) + controller = @controller.new.call(@action, env) + end + end + + class ActionMiddleware + def initialize(controller, action) + @controller, @action = controller, action + end + + def call(env) + controller = @controller.new + controller.app = @app + controller.call(@action, env) + end + + def new(app) + @app = app + self + end end # Return a rack endpoint for the given action. Memoize the endpoint, so @@ -89,9 +116,12 @@ module ActionController # Proc:: A rack application def self.action(name) @actions ||= {} - @actions[name.to_s] ||= proc do |env| - new.call(name, env) - end + @actions[name.to_s] ||= ActionEndpoint.new(self, name) + end + + def self.middleware(name) + @middlewares ||= {} + @middlewares[name.to_s] ||= ActionMiddleware.new(self, name) end end end diff --git a/actionpack/lib/action_controller/metal/rack_convenience.rb b/actionpack/lib/action_controller/metal/rack_convenience.rb index 5fac445dab..a80569c530 100644 --- a/actionpack/lib/action_controller/metal/rack_convenience.rb +++ b/actionpack/lib/action_controller/metal/rack_convenience.rb @@ -5,7 +5,7 @@ module ActionController included do delegate :headers, :status=, :location=, :content_type=, :status, :location, :content_type, :to => "@_response" - attr_internal :request, :response + attr_internal :request end def call(name, env) @@ -19,12 +19,6 @@ module ActionController @_params ||= @_request.parameters end - # :api: private - def to_a - @_response.prepare! - @_response.to_a - end - def response_body=(body) response.body = body if response super diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index 055f29a972..e457450059 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -161,13 +161,16 @@ module ActionDispatch # :nodoc: headers[CONTENT_TYPE] = type end - def prepare! + def to_a assign_default_content_type_and_charset! handle_conditional_get! self["Set-Cookie"] = @cookie.join("\n") self["ETag"] = @etag if @etag + super end + alias prepare! to_a + def each(&callback) if @body.respond_to?(:call) @writer = lambda { |x| callback.call(x) } diff --git a/actionpack/test/new_base/metal_test.rb b/actionpack/test/new_base/metal_test.rb new file mode 100644 index 0000000000..c7c45b5cc9 --- /dev/null +++ b/actionpack/test/new_base/metal_test.rb @@ -0,0 +1,45 @@ +require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper") + +module MetalTest + class MetalMiddleware < ActionController::Metal + def index + if env["PATH_INFO"] =~ /authed/ + self.response = app.call(env) + else + self.response_body = "Not authed!" + self.status = 401 + end + end + end + + class Endpoint + def call(env) + [200, {}, "Hello World"] + end + end + + class TestMiddleware < ActiveSupport::TestCase + def setup + @app = Rack::Builder.new do + use MetalMiddleware.middleware(:index) + run Endpoint.new + end.to_app + end + + test "it can call the next app by using @app" do + env = Rack::MockRequest.env_for("/authed") + response = @app.call(env) + + assert_equal "Hello World", response[2] + end + + test "it can return a response using the normal AC::Metal techniques" do + env = Rack::MockRequest.env_for("/") + response = @app.call(env) + + assert_equal "Not authed!", response[2] + assert_equal 401, response[0] + end + end +end + |