diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb index 54980aa453e5bc1fc8a4eb507b7cba32a589e352..129e0bbd3cd2b60206d0b25cf8d84414d253e928 100644 --- a/actionpack/lib/action_controller/metal.rb +++ b/actionpack/lib/action_controller/metal.rb @@ -132,6 +132,12 @@ def self.controller_name @controller_name ||= name.demodulize.sub(/Controller$/, '').underscore end + def self.make_response!(request) + ActionDispatch::Response.new.tap do |res| + res.request = request + end + end + # Delegates to the class' controller_name def controller_name self.class.controller_name @@ -143,11 +149,10 @@ def controller_name # and response object available. You might wish to control the # environment and response manually for performance reasons. - attr_internal :headers, :response, :request - delegate :session, :to => "@_request" + attr_internal :response, :request + delegate :session, :headers, :to => "@_request" def initialize - @_headers = {"Content-Type" => "text/html"} @_status = 200 @_request = nil @_response = nil @@ -168,7 +173,7 @@ def params=(val) # in Renderer and Redirector. def content_type=(type) - headers["Content-Type"] = type.to_s + response.content_type = type end def content_type @@ -199,6 +204,7 @@ def status=(status) def response_body=(body) body = [body] unless body.nil? || body.respond_to?(:each) + response.body = body super end @@ -207,12 +213,17 @@ def performed? response_body || (response && response.committed?) end - def dispatch(name, request) #:nodoc: + def dispatch(name, request, response) #:nodoc: set_request!(request) + set_response!(response) process(name) to_a end + def set_response!(response) # :nodoc: + @_response = response + end + def set_request!(request) #:nodoc: @_request = request @_request.controller_instance = self @@ -253,20 +264,26 @@ class << self; deprecate :call; end def self.action(name) if middleware_stack.any? middleware_stack.build(name) do |env| - new.dispatch(name, ActionDispatch::Request.new(env)) + req = ActionDispatch::Request.new(env) + res = make_response! req + new.dispatch(name, req, res) end else - lambda { |env| new.dispatch(name, ActionDispatch::Request.new(env)) } + lambda { |env| + req = ActionDispatch::Request.new(env) + res = make_response! req + new.dispatch(name, req, res) + } end end # Direct dispatch to the controller. Instantiates the controller, then # executes the action named +name+. - def self.dispatch(name, req) + def self.dispatch(name, req, res) if middleware_stack.any? - middleware_stack.build(name) { |env| new.dispatch(name, req) }.call req.env + middleware_stack.build(name) { |env| new.dispatch(name, req, res) }.call req.env else - new.dispatch(name, req) + new.dispatch(name, req, res) end end end diff --git a/actionpack/lib/action_controller/metal/head.rb b/actionpack/lib/action_controller/metal/head.rb index 056962b38cc69a3e32f824d4d502241ab1666fd3..7dbd5ef328a03dbc85bd4edee7c9fe7764fd929c 100644 --- a/actionpack/lib/action_controller/metal/head.rb +++ b/actionpack/lib/action_controller/metal/head.rb @@ -36,6 +36,8 @@ def head(status, options = {}) headers[key.to_s.dasherize.split('-').each { |v| v[0] = v[0].chr.upcase }.join('-')] = value.to_s end + response.status = Rack::Utils.status_code(status) + self.status = status self.location = url_for(location) if location @@ -44,9 +46,6 @@ def head(status, options = {}) if include_content?(self.response_code) self.content_type = content_type || (Mime[formats.first] if formats) self.response.charset = false if self.response - else - headers.delete('Content-Type') - headers.delete('Content-Length') end true diff --git a/actionpack/lib/action_controller/metal/rack_delegation.rb b/actionpack/lib/action_controller/metal/rack_delegation.rb index eb8bca1d921c48715812d35be65d085d47f6967d..5ba9a47d6344c8bfb9acf553477547b2ee8ba377 100644 --- a/actionpack/lib/action_controller/metal/rack_delegation.rb +++ b/actionpack/lib/action_controller/metal/rack_delegation.rb @@ -12,17 +12,6 @@ module ClassMethods def build_with_env(env = {}) #:nodoc: new.tap { |c| c.set_request! ActionDispatch::Request.new(env) } end - - def make_response!(request) - ActionDispatch::Response.new.tap do |res| - res.request = request - end - end - end - - def set_request!(request) #:nodoc: - super - set_response!(request) end def response_body=(body) @@ -33,11 +22,5 @@ def response_body=(body) def reset_session @_request.reset_session end - - private - - def set_response!(request) - @_response = self.class.make_response! request - end end end diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index fd92e892310e28330b7081c6dd3d5b5302349dc1..c83b682f6942877f881fef7c66c1517bd029730a 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -65,7 +65,7 @@ class Response CONTENT_TYPE = "Content-Type".freeze SET_COOKIE = "Set-Cookie".freeze LOCATION = "Location".freeze - NO_CONTENT_CODES = [204, 304] + NO_CONTENT_CODES = [100, 101, 102, 204, 205, 304] cattr_accessor(:default_charset) { "utf-8" } cattr_accessor(:default_headers) @@ -396,6 +396,7 @@ def rack_response(status, header) if NO_CONTENT_CODES.include?(@status) header.delete CONTENT_TYPE + header.delete 'Content-Length' [status, header, []] else [status, header, RackBody.new(self)] diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 3e3a424df3928101df3164667619d4d92e850fa8..e4b8d5993e1b7350af85111500521c35cef89776 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -27,8 +27,10 @@ def initialize(raise_on_name_error) def dispatcher?; true; end def serve(req) - params = req.path_parameters - dispatch(controller(req), params[:action], req) + params = req.path_parameters + controller = controller req + res = controller.make_response! req + dispatch(controller, params[:action], req, res) rescue NameError => e if @raise_on_name_error raise ActionController::RoutingError, e.message, e.backtrace @@ -43,8 +45,8 @@ def controller(req) req.controller_class end - def dispatch(controller, action, req) - controller.dispatch(action, req) + def dispatch(controller, action, req, res) + controller.dispatch(action, req, res) end end diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb index 39ae8cf8993a65d1464bc235d2d2fddd5cfb2419..1954324222b04c85adefa0c677ae76f143d53700 100644 --- a/actionpack/test/abstract_unit.rb +++ b/actionpack/test/abstract_unit.rb @@ -121,12 +121,16 @@ def self.build_app(routes = nil) class DeadEndRoutes < ActionDispatch::Routing::RouteSet # Stub Rails dispatcher so it does not get controller references and # simply return the controller#action as Rack::Body. - class NullController + class NullController < ::ActionController::Metal def initialize(controller_name) @controller = controller_name end - def dispatch(action, req) + def make_response!(request) + self.class.make_response! request + end + + def dispatch(action, req, res) [200, {'Content-Type' => 'text/html'}, ["#{@controller}##{action}"]] end end diff --git a/actionpack/test/controller/base_test.rb b/actionpack/test/controller/base_test.rb index d9374ce9c3064cc5b5afbfa0efd561009c1961f8..fb60dbd99362c7feccf2f0f6aab6f85823285e06 100644 --- a/actionpack/test/controller/base_test.rb +++ b/actionpack/test/controller/base_test.rb @@ -93,6 +93,8 @@ def test_no_deprecation_when_action_view_record_identifier_is_included class ControllerInstanceTests < ActiveSupport::TestCase def setup @empty = EmptyController.new + @empty.set_request!(ActionDispatch::Request.new({})) + @empty.set_response!(EmptyController.make_response!(@empty.request)) @contained = Submodule::ContainedEmptyController.new @empty_controllers = [@empty, @contained] end diff --git a/actionpack/test/controller/new_base/bare_metal_test.rb b/actionpack/test/controller/new_base/bare_metal_test.rb index 951674a3992635a1fa0e8b7515b304fc524ddc29..77c9c13e968f80e6714e22cff5e57fb200f82817 100644 --- a/actionpack/test/controller/new_base/bare_metal_test.rb +++ b/actionpack/test/controller/new_base/bare_metal_test.rb @@ -28,6 +28,8 @@ class BareTest < ActiveSupport::TestCase test "response_body value is wrapped in an array when the value is a String" do controller = BareController.new + controller.set_request!(ActionDispatch::Request.new({})) + controller.set_response!(BareController.make_response!(controller.request)) controller.index assert_equal ["Hello world"], controller.response_body end diff --git a/actionpack/test/controller/new_base/render_html_test.rb b/actionpack/test/controller/new_base/render_html_test.rb index fe11501eebea70c5b6ba0503a18385ef19055feb..e9ea57e329b636ccb3b278cd5b388ca5812d8c58 100644 --- a/actionpack/test/controller/new_base/render_html_test.rb +++ b/actionpack/test/controller/new_base/render_html_test.rb @@ -179,7 +179,7 @@ class RenderHtmlTest < Rack::TestCase test "rendering from minimal controller returns response with text/html content type" do get "/render_html/minimal/index" - assert_content_type "text/html" + assert_content_type "text/html; charset=utf-8" end test "rendering from normal controller returns response with text/html content type" do diff --git a/actionpack/test/controller/new_base/render_plain_test.rb b/actionpack/test/controller/new_base/render_plain_test.rb index 0e36d36b50c15aae838661849fc88b25d62eddc8..0881442bd0ba40a2408826a3869cf2cc17928978 100644 --- a/actionpack/test/controller/new_base/render_plain_test.rb +++ b/actionpack/test/controller/new_base/render_plain_test.rb @@ -157,7 +157,7 @@ class RenderPlainTest < Rack::TestCase test "rendering from minimal controller returns response with text/plain content type" do get "/render_plain/minimal/index" - assert_content_type "text/plain" + assert_content_type "text/plain; charset=utf-8" end test "rendering from normal controller returns response with text/plain content type" do