From 6bbe965ccdcef2d7e713e65175722718d325b2bd Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Wed, 27 May 2009 10:40:43 +0200 Subject: Reduce the cost of using ActionController::Http significantly by: * Removing the dependency on AD::Request and AD::Response * Moving the logic for the request and response object into a new module that is included by default. * Changing Renderer and Redirector to use self.headers, self.content_type, and self.status, which have very basic default implementations on AC::Http. When RackConvenience is included (which it is by default on AC::Base), the full Request/Response logic is used instead of the simple logic. --- actionpack/lib/action_controller/new_base.rb | 1 + actionpack/lib/action_controller/new_base/base.rb | 1 + .../action_controller/new_base/conditional_get.rb | 3 ++ actionpack/lib/action_controller/new_base/http.rb | 42 +++++++++++++++------- .../action_controller/new_base/rack_convenience.rb | 34 ++++++++++++++++++ .../lib/action_controller/new_base/redirector.rb | 4 +-- .../action_controller/new_base/render_options.rb | 8 ++--- .../lib/action_controller/new_base/renderer.rb | 13 +++---- .../lib/action_controller/new_base/session.rb | 4 +++ .../lib/action_controller/new_base/testing.rb | 2 ++ .../lib/action_controller/new_base/url_for.rb | 4 +++ 11 files changed, 88 insertions(+), 28 deletions(-) create mode 100644 actionpack/lib/action_controller/new_base/rack_convenience.rb (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/new_base.rb b/actionpack/lib/action_controller/new_base.rb index e9e89769f1..df256985ac 100644 --- a/actionpack/lib/action_controller/new_base.rb +++ b/actionpack/lib/action_controller/new_base.rb @@ -4,6 +4,7 @@ module ActionController autoload :HideActions, "action_controller/new_base/hide_actions" autoload :Http, "action_controller/new_base/http" autoload :Layouts, "action_controller/new_base/layouts" + autoload :RackConvenience, "action_controller/new_base/rack_convenience" autoload :Rails2Compatibility, "action_controller/new_base/compatibility" autoload :Redirector, "action_controller/new_base/redirector" autoload :Renderer, "action_controller/new_base/renderer" diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb index 3477fc0403..6fe7793030 100644 --- a/actionpack/lib/action_controller/new_base/base.rb +++ b/actionpack/lib/action_controller/new_base/base.rb @@ -14,6 +14,7 @@ module ActionController include ActionController::Renderers::All include ActionController::Layouts include ActionController::ConditionalGet + include ActionController::RackConvenience # Legacy modules include SessionManagement diff --git a/actionpack/lib/action_controller/new_base/conditional_get.rb b/actionpack/lib/action_controller/new_base/conditional_get.rb index 116ce34494..7d41ee6371 100644 --- a/actionpack/lib/action_controller/new_base/conditional_get.rb +++ b/actionpack/lib/action_controller/new_base/conditional_get.rb @@ -1,5 +1,8 @@ module ActionController module ConditionalGet + extend ActiveSupport::DependencyModule + + depends_on RackConvenience # Sets the etag, last_modified, or both on the response and renders a # "304 Not Modified" response if the request is already fresh. diff --git a/actionpack/lib/action_controller/new_base/http.rb b/actionpack/lib/action_controller/new_base/http.rb index 2525e221a6..7ff490bb9c 100644 --- a/actionpack/lib/action_controller/new_base/http.rb +++ b/actionpack/lib/action_controller/new_base/http.rb @@ -6,7 +6,7 @@ module ActionController abstract! # :api: public - attr_internal :request, :response, :params + attr_internal :params, :env # :api: public def self.controller_name @@ -36,32 +36,48 @@ module ActionController controller.call(env).to_rack end - delegate :headers, :to => "@_response" + # The details below can be overridden to support a specific + # Request and Response object. The default ActionController::Base + # implementation includes RackConvenience, which makes a request + # and response object available. You might wish to control the + # environment and response manually for performance reasons. - def params - @_params ||= @_request.parameters + attr_internal :status, :headers, :content_type + + def initialize(*) + @_headers = {} + super + end + + # Basic implements for content_type=, location=, and headers are + # provided to reduce the dependency on the RackConvenience module + # in Renderer and Redirector. + + def content_type=(type) + headers["Content-Type"] = type.to_s + end + + def location=(url) + headers["Location"] = url end # :api: private def call(name, env) - @_request = ActionDispatch::Request.new(env) - @_response = ActionDispatch::Response.new - @_response.request = request + @_env = env process(name) to_rack end + # :api: private + def to_rack + [status, headers, response_body] + end + def self.action(name) @actions ||= {} @actions[name.to_s] ||= proc do |env| new.call(name, env) end end - - # :api: private - def to_rack - @_response.prepare! - @_response.to_a - end end end diff --git a/actionpack/lib/action_controller/new_base/rack_convenience.rb b/actionpack/lib/action_controller/new_base/rack_convenience.rb new file mode 100644 index 0000000000..0422ab2f14 --- /dev/null +++ b/actionpack/lib/action_controller/new_base/rack_convenience.rb @@ -0,0 +1,34 @@ +module ActionController + module RackConvenience + extend ActiveSupport::DependencyModule + + included do + delegate :headers, :status=, :location=, + :status, :location, :content_type, :to => "@_response" + attr_internal :request, :response + end + + def call(name, env) + @_request = ActionDispatch::Request.new(env) + @_response = ActionDispatch::Response.new + @_response.request = request + super + end + + def params + @_params ||= @_request.parameters + end + + # :api: private + def to_rack + @_response.prepare! + @_response.to_a + end + + def response_body=(body) + response.body = body if response + super + end + + end +end \ No newline at end of file diff --git a/actionpack/lib/action_controller/new_base/redirector.rb b/actionpack/lib/action_controller/new_base/redirector.rb index ff7b74341c..b2da412edf 100644 --- a/actionpack/lib/action_controller/new_base/redirector.rb +++ b/actionpack/lib/action_controller/new_base/redirector.rb @@ -11,8 +11,8 @@ module ActionController def redirect_to(url, status) #:doc: raise AbstractController::DoubleRenderError if response_body logger.info("Redirected to #{url}") if logger && logger.info? - response.status = status - response.location = url.gsub(/[\r\n]/, '') + self.status = status + self.location = url.gsub(/[\r\n]/, '') self.response_body = "You are being redirected." end end diff --git a/actionpack/lib/action_controller/new_base/render_options.rb b/actionpack/lib/action_controller/new_base/render_options.rb index 581a92cb7b..48575ec0bd 100644 --- a/actionpack/lib/action_controller/new_base/render_options.rb +++ b/actionpack/lib/action_controller/new_base/render_options.rb @@ -57,7 +57,7 @@ module ActionController def _render_json(json, options) json = ActiveSupport::JSON.encode(json) unless json.respond_to?(:to_str) json = "#{options[:callback]}(#{json})" unless options[:callback].blank? - response.content_type ||= Mime::JSON + self.content_type ||= Mime::JSON self.response_body = json end end @@ -67,7 +67,7 @@ module ActionController register_renderer :js def _render_js(js, options) - response.content_type ||= Mime::JS + self.content_type ||= Mime::JS self.response_body = js end end @@ -77,7 +77,7 @@ module ActionController register_renderer :xml def _render_xml(xml, options) - response.content_type ||= Mime::XML + self.content_type ||= Mime::XML self.response_body = xml.respond_to?(:to_xml) ? xml.to_xml : xml end end @@ -88,7 +88,7 @@ module ActionController def _render_update(proc, options) generator = ActionView::Helpers::PrototypeHelper::JavaScriptGenerator.new(_action_view, &proc) - response.content_type = Mime::JS + self.content_type = Mime::JS self.response_body = generator.to_s end end diff --git a/actionpack/lib/action_controller/new_base/renderer.rb b/actionpack/lib/action_controller/new_base/renderer.rb index 987751a601..fb6fe4aee6 100644 --- a/actionpack/lib/action_controller/new_base/renderer.rb +++ b/actionpack/lib/action_controller/new_base/renderer.rb @@ -8,16 +8,11 @@ module ActionController self.formats = request.formats.map {|x| x.to_sym} super end - - def response_body=(body) - response.body = body if response - super - end def render(options) super options[:_template] ||= _action_view._partial - response.content_type ||= begin + self.content_type ||= begin mime = options[:_template].mime_type formats.include?(mime && mime.to_sym) || formats.include?(:all) ? mime : Mime::Type.lookup_by_extension(formats.first) end @@ -76,9 +71,9 @@ module ActionController def _process_options(options) status, content_type, location = options.values_at(:status, :content_type, :location) - response.status = status if status - response.content_type = content_type if content_type - response.headers["Location"] = url_for(location) if location + self.status = status if status + self.content_type = content_type if content_type + self.headers["Location"] = url_for(location) if location end end end diff --git a/actionpack/lib/action_controller/new_base/session.rb b/actionpack/lib/action_controller/new_base/session.rb index a8715555fb..9ee3e9e136 100644 --- a/actionpack/lib/action_controller/new_base/session.rb +++ b/actionpack/lib/action_controller/new_base/session.rb @@ -1,5 +1,9 @@ module ActionController module Session + extend ActiveSupport::DependencyModule + + depends_on RackConvenience + def session @_request.session end diff --git a/actionpack/lib/action_controller/new_base/testing.rb b/actionpack/lib/action_controller/new_base/testing.rb index 78051a6252..596f613a13 100644 --- a/actionpack/lib/action_controller/new_base/testing.rb +++ b/actionpack/lib/action_controller/new_base/testing.rb @@ -2,6 +2,8 @@ module ActionController module Testing extend ActiveSupport::DependencyModule + depends_on RackConvenience + # OMG MEGA HAX def process_with_new_base_test(request, response) @_request = request diff --git a/actionpack/lib/action_controller/new_base/url_for.rb b/actionpack/lib/action_controller/new_base/url_for.rb index 94de9fab50..e6e5d3acce 100644 --- a/actionpack/lib/action_controller/new_base/url_for.rb +++ b/actionpack/lib/action_controller/new_base/url_for.rb @@ -1,5 +1,9 @@ module ActionController module UrlFor + extend ActiveSupport::DependencyModule + + depends_on RackConvenience + def process_action(*) initialize_current_url super -- cgit v1.2.3