Rename AbstractResponse to Response and inheirt from Rack::Response
This commit is contained in:
parent
a14bbd7a85
commit
fda62ecf70
|
@ -42,7 +42,6 @@ module ActionController
|
|||
end
|
||||
|
||||
autoload :AbstractRequest, 'action_controller/request'
|
||||
autoload :AbstractResponse, 'action_controller/response'
|
||||
autoload :Base, 'action_controller/base'
|
||||
autoload :Benchmarking, 'action_controller/benchmarking'
|
||||
autoload :Caching, 'action_controller/caching'
|
||||
|
@ -61,8 +60,8 @@ module ActionController
|
|||
autoload :MimeResponds, 'action_controller/mime_responds'
|
||||
autoload :PolymorphicRoutes, 'action_controller/polymorphic_routes'
|
||||
autoload :RackRequest, 'action_controller/rack_process'
|
||||
autoload :RackResponse, 'action_controller/rack_process'
|
||||
autoload :RecordIdentifier, 'action_controller/record_identifier'
|
||||
autoload :Response, 'action_controller/response'
|
||||
autoload :RequestForgeryProtection, 'action_controller/request_forgery_protection'
|
||||
autoload :Rescue, 'action_controller/rescue'
|
||||
autoload :Resources, 'action_controller/resources'
|
||||
|
|
|
@ -98,7 +98,7 @@ module ActionController
|
|||
|
||||
def _call(env)
|
||||
@request = RackRequest.new(env)
|
||||
@response = RackResponse.new
|
||||
@response = Response.new
|
||||
dispatch
|
||||
end
|
||||
|
||||
|
|
|
@ -181,7 +181,7 @@ module ActionController
|
|||
# - +headers+: Additional HTTP headers to pass, as a Hash. The keys will
|
||||
# automatically be upcased, with the prefix 'HTTP_' added if needed.
|
||||
#
|
||||
# This method returns an AbstractResponse object, which one can use to
|
||||
# This method returns an Response object, which one can use to
|
||||
# inspect the details of the response. Furthermore, if this method was
|
||||
# called from an ActionController::IntegrationTest object, then that
|
||||
# object's <tt>@response</tt> instance variable will point to the same
|
||||
|
@ -331,10 +331,10 @@ module ActionController
|
|||
@response = @controller.response
|
||||
else
|
||||
# Decorate responses from Rack Middleware and Rails Metal
|
||||
# as an AbstractResponse for the purposes of integration testing
|
||||
@response = AbstractResponse.new
|
||||
# as an Response for the purposes of integration testing
|
||||
@response = Response.new
|
||||
@response.status = status.to_s
|
||||
@response.headers = @headers
|
||||
@response.headers.replace(@headers)
|
||||
@response.body = @body
|
||||
end
|
||||
|
||||
|
|
|
@ -70,81 +70,4 @@ module ActionController #:nodoc:
|
|||
@env['rack.session'] = {}
|
||||
end
|
||||
end
|
||||
|
||||
class RackResponse < AbstractResponse #:nodoc:
|
||||
def initialize
|
||||
@writer = lambda { |x| @body << x }
|
||||
@block = nil
|
||||
super()
|
||||
end
|
||||
|
||||
def to_a(&block)
|
||||
@block = block
|
||||
if [204, 304].include?(status.to_i)
|
||||
headers.delete("Content-Type")
|
||||
[status, headers.to_hash, []]
|
||||
else
|
||||
[status, headers.to_hash, self]
|
||||
end
|
||||
end
|
||||
|
||||
def each(&callback)
|
||||
if @body.respond_to?(:call)
|
||||
@writer = lambda { |x| callback.call(x) }
|
||||
@body.call(self, self)
|
||||
elsif @body.is_a?(String)
|
||||
@body.each_line(&callback)
|
||||
else
|
||||
@body.each(&callback)
|
||||
end
|
||||
|
||||
@writer = callback
|
||||
@block.call(self) if @block
|
||||
end
|
||||
|
||||
def write(str)
|
||||
@writer.call str.to_s
|
||||
str
|
||||
end
|
||||
|
||||
def close
|
||||
@body.close if @body.respond_to?(:close)
|
||||
end
|
||||
|
||||
def empty?
|
||||
@block == nil && @body.empty?
|
||||
end
|
||||
|
||||
def prepare!
|
||||
super
|
||||
|
||||
convert_language!
|
||||
convert_expires!
|
||||
set_status!
|
||||
end
|
||||
|
||||
private
|
||||
def convert_language!
|
||||
headers["Content-Language"] = headers.delete("language") if headers["language"]
|
||||
end
|
||||
|
||||
def convert_expires!
|
||||
headers["Expires"] = headers.delete("") if headers["expires"]
|
||||
end
|
||||
|
||||
def convert_content_type!
|
||||
super
|
||||
headers['Content-Type'] = headers.delete('type') || "text/html"
|
||||
headers['Content-Type'] += "; charset=" + headers.delete('charset') if headers['charset']
|
||||
end
|
||||
|
||||
def set_content_length!
|
||||
super
|
||||
headers["Content-Length"] = headers["Content-Length"].to_s if headers["Content-Length"]
|
||||
end
|
||||
|
||||
def set_status!
|
||||
self.status ||= "200 OK"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,24 +1,25 @@
|
|||
require 'digest/md5'
|
||||
|
||||
module ActionController # :nodoc:
|
||||
# Represents an HTTP response generated by a controller action. One can use an
|
||||
# ActionController::AbstractResponse object to retrieve the current state of the
|
||||
# response, or customize the response. An AbstractResponse object can either
|
||||
# represent a "real" HTTP response (i.e. one that is meant to be sent back to the
|
||||
# web browser) or a test response (i.e. one that is generated from integration
|
||||
# tests). See CgiResponse and TestResponse, respectively.
|
||||
# Represents an HTTP response generated by a controller action. One can use
|
||||
# an ActionController::Response object to retrieve the current state
|
||||
# of the response, or customize the response. An Response object can
|
||||
# either represent a "real" HTTP response (i.e. one that is meant to be sent
|
||||
# back to the web browser) or a test response (i.e. one that is generated
|
||||
# from integration tests). See CgiResponse and TestResponse, respectively.
|
||||
#
|
||||
# AbstractResponse is mostly a Ruby on Rails framework implement detail, and should
|
||||
# never be used directly in controllers. Controllers should use the methods defined
|
||||
# in ActionController::Base instead. For example, if you want to set the HTTP
|
||||
# response's content MIME type, then use ActionControllerBase#headers instead of
|
||||
# AbstractResponse#headers.
|
||||
# Response is mostly a Ruby on Rails framework implement detail, and
|
||||
# should never be used directly in controllers. Controllers should use the
|
||||
# methods defined in ActionController::Base instead. For example, if you want
|
||||
# to set the HTTP response's content MIME type, then use
|
||||
# ActionControllerBase#headers instead of Response#headers.
|
||||
#
|
||||
# Nevertheless, integration tests may want to inspect controller responses in more
|
||||
# detail, and that's when AbstractResponse can be useful for application developers.
|
||||
# Integration test methods such as ActionController::Integration::Session#get and
|
||||
# ActionController::Integration::Session#post return objects of type TestResponse
|
||||
# (which are of course also of type AbstractResponse).
|
||||
# Nevertheless, integration tests may want to inspect controller responses in
|
||||
# more detail, and that's when Response can be useful for application
|
||||
# developers. Integration test methods such as
|
||||
# ActionController::Integration::Session#get and
|
||||
# ActionController::Integration::Session#post return objects of type
|
||||
# TestResponse (which are of course also of type Response).
|
||||
#
|
||||
# For example, the following demo integration "test" prints the body of the
|
||||
# controller response to the console:
|
||||
|
@ -29,22 +30,24 @@ module ActionController # :nodoc:
|
|||
# puts @response.body
|
||||
# end
|
||||
# end
|
||||
class AbstractResponse
|
||||
class Response < Rack::Response
|
||||
DEFAULT_HEADERS = { "Cache-Control" => "no-cache" }
|
||||
attr_accessor :request
|
||||
|
||||
attr_accessor :status
|
||||
# The body content (e.g. HTML) of the response, as a String.
|
||||
attr_accessor :body
|
||||
# The headers of the response, as a Hash. It maps header names to header values.
|
||||
attr_accessor :headers
|
||||
attr_accessor :session, :cookies, :assigns, :template, :layout
|
||||
attr_accessor :redirected_to, :redirected_to_method_params
|
||||
|
||||
delegate :default_charset, :to => 'ActionController::Base'
|
||||
|
||||
def initialize
|
||||
@body, @headers, @session, @assigns = "", DEFAULT_HEADERS.merge("cookie" => []), [], []
|
||||
@status = 200
|
||||
@header = DEFAULT_HEADERS.merge("cookie" => [])
|
||||
|
||||
@writer = lambda { |x| @body << x }
|
||||
@block = nil
|
||||
|
||||
@body = "",
|
||||
@session, @assigns = [], []
|
||||
end
|
||||
|
||||
def location; headers['Location'] end
|
||||
|
@ -140,9 +143,31 @@ module ActionController # :nodoc:
|
|||
handle_conditional_get!
|
||||
set_content_length!
|
||||
convert_content_type!
|
||||
|
||||
convert_language!
|
||||
convert_expires!
|
||||
set_cookies!
|
||||
end
|
||||
|
||||
def each(&callback)
|
||||
if @body.respond_to?(:call)
|
||||
@writer = lambda { |x| callback.call(x) }
|
||||
@body.call(self, self)
|
||||
elsif @body.is_a?(String)
|
||||
@body.each_line(&callback)
|
||||
else
|
||||
@body.each(&callback)
|
||||
end
|
||||
|
||||
@writer = callback
|
||||
@block.call(self) if @block
|
||||
end
|
||||
|
||||
def write(str)
|
||||
@writer.call str.to_s
|
||||
str
|
||||
end
|
||||
|
||||
private
|
||||
def handle_conditional_get!
|
||||
if etag? || last_modified?
|
||||
|
@ -171,23 +196,25 @@ module ActionController # :nodoc:
|
|||
end
|
||||
|
||||
def convert_content_type!
|
||||
if content_type = headers.delete("Content-Type")
|
||||
self.headers["type"] = content_type
|
||||
end
|
||||
if content_type = headers.delete("Content-type")
|
||||
self.headers["type"] = content_type
|
||||
end
|
||||
if content_type = headers.delete("content-type")
|
||||
self.headers["type"] = content_type
|
||||
end
|
||||
headers['Content-Type'] ||= "text/html"
|
||||
headers['Content-Type'] += "; charset=" + headers.delete('charset') if headers['charset']
|
||||
end
|
||||
|
||||
# Don't set the Content-Length for block-based bodies as that would mean reading it all into memory. Not nice
|
||||
# for, say, a 2GB streaming file.
|
||||
# Don't set the Content-Length for block-based bodies as that would mean
|
||||
# reading it all into memory. Not nice for, say, a 2GB streaming file.
|
||||
def set_content_length!
|
||||
unless body.respond_to?(:call) || (status && status.to_s[0..2] == '304')
|
||||
self.headers["Content-Length"] ||= body.size
|
||||
end
|
||||
headers["Content-Length"] = headers["Content-Length"].to_s if headers["Content-Length"]
|
||||
end
|
||||
|
||||
def convert_language!
|
||||
headers["Content-Language"] = headers.delete("language") if headers["language"]
|
||||
end
|
||||
|
||||
def convert_expires!
|
||||
headers["Expires"] = headers.delete("") if headers["expires"]
|
||||
end
|
||||
|
||||
def set_cookies!
|
||||
|
|
|
@ -290,8 +290,8 @@ module ActionController #:nodoc:
|
|||
# TestResponse, which represent the HTTP response results of the requested
|
||||
# controller actions.
|
||||
#
|
||||
# See AbstractResponse for more information on controller response objects.
|
||||
class TestResponse < AbstractResponse
|
||||
# See Response for more information on controller response objects.
|
||||
class TestResponse < Response
|
||||
include TestResponseBehavior
|
||||
|
||||
def recycle!
|
||||
|
@ -435,7 +435,7 @@ module ActionController #:nodoc:
|
|||
end
|
||||
|
||||
def session
|
||||
@response.session
|
||||
@request.session
|
||||
end
|
||||
|
||||
def flash
|
||||
|
|
|
@ -500,17 +500,17 @@ class ActionPackHeaderTest < ActionController::TestCase
|
|||
|
||||
def test_rendering_xml_sets_content_type
|
||||
process :hello_xml_world
|
||||
assert_equal('application/xml; charset=utf-8', @response.headers['type'])
|
||||
assert_equal('application/xml; charset=utf-8', @response.headers['Content-Type'])
|
||||
end
|
||||
|
||||
def test_rendering_xml_respects_content_type
|
||||
@response.headers['type'] = 'application/pdf'
|
||||
process :hello_xml_world
|
||||
assert_equal('application/pdf; charset=utf-8', @response.headers['type'])
|
||||
assert_equal('application/pdf; charset=utf-8', @response.headers['Content-Type'])
|
||||
end
|
||||
|
||||
def test_render_text_with_custom_content_type
|
||||
get :render_text_with_custom_content_type
|
||||
assert_equal 'application/rss+xml; charset=utf-8', @response.headers['type']
|
||||
assert_equal 'application/rss+xml; charset=utf-8', @response.headers['Content-Type']
|
||||
end
|
||||
end
|
||||
|
|
|
@ -59,7 +59,7 @@ class CookieTest < Test::Unit::TestCase
|
|||
get :authenticate_for_fourteen_days
|
||||
assert_equal ["user_name=david; path=/; expires=Mon, 10 Oct 2005 05:00:00 GMT"], @response.headers["Set-Cookie"]
|
||||
assert_equal({"user_name" => ["david"]}, @response.cookies)
|
||||
end
|
||||
end
|
||||
|
||||
def test_setting_cookie_for_fourteen_days_with_symbols
|
||||
get :authenticate_for_fourteen_days_with_symbols
|
||||
|
@ -71,7 +71,7 @@ class CookieTest < Test::Unit::TestCase
|
|||
get :authenticate_with_http_only
|
||||
assert_equal ["user_name=david; path=/; HttpOnly"], @response.headers["Set-Cookie"]
|
||||
assert_equal({"user_name" => ["david"]}, @response.cookies)
|
||||
end
|
||||
end
|
||||
|
||||
def test_multiple_cookies
|
||||
get :set_multiple_cookies
|
||||
|
@ -79,7 +79,7 @@ class CookieTest < Test::Unit::TestCase
|
|||
assert_equal "user_name=david; path=/; expires=Mon, 10 Oct 2005 05:00:00 GMT", @response.headers["Set-Cookie"][0]
|
||||
assert_equal "login=XJ-122; path=/", @response.headers["Set-Cookie"][1]
|
||||
assert_equal({"login" => ["XJ-122"], "user_name" => ["david"]}, @response.cookies)
|
||||
end
|
||||
end
|
||||
|
||||
def test_setting_test_cookie
|
||||
assert_nothing_raised { get :access_frozen_cookies }
|
||||
|
@ -89,7 +89,7 @@ class CookieTest < Test::Unit::TestCase
|
|||
get :logout
|
||||
assert_equal ["user_name=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT"], @response.headers["Set-Cookie"]
|
||||
assert_equal({"user_name" => []}, @response.cookies)
|
||||
end
|
||||
end
|
||||
|
||||
def test_cookiejar_accessor
|
||||
@request.cookies["user_name"] = CGI::Cookie.new("name" => "user_name", "value" => "david", "expires" => Time.local(2025, 10, 10))
|
||||
|
|
|
@ -229,7 +229,7 @@ end
|
|||
class RackResponseTest < BaseRackTest
|
||||
def setup
|
||||
super
|
||||
@response = ActionController::RackResponse.new
|
||||
@response = ActionController::Response.new
|
||||
end
|
||||
|
||||
def test_simple_output
|
||||
|
@ -237,7 +237,7 @@ class RackResponseTest < BaseRackTest
|
|||
@response.prepare!
|
||||
|
||||
status, headers, body = @response.to_a
|
||||
assert_equal "200 OK", status
|
||||
assert_equal 200, status
|
||||
assert_equal({
|
||||
"Content-Type" => "text/html; charset=utf-8",
|
||||
"Cache-Control" => "private, max-age=0, must-revalidate",
|
||||
|
@ -258,7 +258,7 @@ class RackResponseTest < BaseRackTest
|
|||
@response.prepare!
|
||||
|
||||
status, headers, body = @response.to_a
|
||||
assert_equal "200 OK", status
|
||||
assert_equal 200, status
|
||||
assert_equal({"Content-Type" => "text/html; charset=utf-8", "Cache-Control" => "no-cache", "Set-Cookie" => []}, headers)
|
||||
|
||||
parts = []
|
||||
|
@ -270,7 +270,7 @@ end
|
|||
class RackResponseHeadersTest < BaseRackTest
|
||||
def setup
|
||||
super
|
||||
@response = ActionController::RackResponse.new
|
||||
@response = ActionController::Response.new
|
||||
@response.status = "200 OK"
|
||||
end
|
||||
|
||||
|
|
|
@ -208,7 +208,7 @@ class TestController < ActionController::Base
|
|||
def greeting
|
||||
# let's just rely on the template
|
||||
end
|
||||
|
||||
|
||||
def blank_response
|
||||
render :text => ' '
|
||||
end
|
||||
|
@ -1099,14 +1099,14 @@ class RenderTest < ActionController::TestCase
|
|||
def test_update_page
|
||||
get :update_page
|
||||
assert_template nil
|
||||
assert_equal 'text/javascript; charset=utf-8', @response.headers['type']
|
||||
assert_equal 'text/javascript; charset=utf-8', @response.headers['Content-Type']
|
||||
assert_equal 2, @response.body.split($/).length
|
||||
end
|
||||
|
||||
def test_update_page_with_instance_variables
|
||||
get :update_page_with_instance_variables
|
||||
assert_template nil
|
||||
assert_equal 'text/javascript; charset=utf-8', @response.headers['type']
|
||||
assert_equal 'text/javascript; charset=utf-8', @response.headers["Content-Type"]
|
||||
assert_match /balance/, @response.body
|
||||
assert_match /\$37/, @response.body
|
||||
end
|
||||
|
@ -1114,7 +1114,7 @@ class RenderTest < ActionController::TestCase
|
|||
def test_update_page_with_view_method
|
||||
get :update_page_with_view_method
|
||||
assert_template nil
|
||||
assert_equal 'text/javascript; charset=utf-8', @response.headers['type']
|
||||
assert_equal 'text/javascript; charset=utf-8', @response.headers["Content-Type"]
|
||||
assert_match /2 people/, @response.body
|
||||
end
|
||||
|
||||
|
@ -1384,7 +1384,7 @@ class EtagRenderTest < ActionController::TestCase
|
|||
@request.host = "www.nextangle.com"
|
||||
@expected_bang_etag = etag_for(expand_key([:foo, 123]))
|
||||
end
|
||||
|
||||
|
||||
def test_render_blank_body_shouldnt_set_etag
|
||||
get :blank_response
|
||||
assert !@response.etag?
|
||||
|
|
Loading…
Reference in New Issue