Skip to content

Commit

Permalink
Rename AbstractResponse to Response and inheirt from Rack::Response
Browse files Browse the repository at this point in the history
  • Loading branch information
josh committed Dec 19, 2008
1 parent a14bbd7 commit fda62ec
Show file tree
Hide file tree
Showing 10 changed files with 86 additions and 137 deletions.
3 changes: 1 addition & 2 deletions actionpack/lib/action_controller.rb
Expand Up @@ -42,7 +42,6 @@ def self.load_all!
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'
Expand All @@ -61,8 +60,8 @@ def self.load_all!
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'
Expand Down
2 changes: 1 addition & 1 deletion actionpack/lib/action_controller/dispatcher.rb
Expand Up @@ -98,7 +98,7 @@ def call(env)

def _call(env)
@request = RackRequest.new(env)
@response = RackResponse.new
@response = Response.new
dispatch
end

Expand Down
8 changes: 4 additions & 4 deletions actionpack/lib/action_controller/integration.rb
Expand Up @@ -181,7 +181,7 @@ def redirect?
# - +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
Expand Down Expand Up @@ -331,10 +331,10 @@ def process(method, path, parameters = nil, headers = nil)
@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

Expand Down
77 changes: 0 additions & 77 deletions actionpack/lib/action_controller/rack_process.rb
Expand Up @@ -70,81 +70,4 @@ def reset_session
@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
95 changes: 61 additions & 34 deletions actionpack/lib/action_controller/response.rb
@@ -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:
Expand All @@ -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
Expand Down Expand Up @@ -140,9 +143,31 @@ def prepare!
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?
Expand Down Expand Up @@ -171,23 +196,25 @@ def set_conditional_cache_control!
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!
Expand Down
6 changes: 3 additions & 3 deletions actionpack/lib/action_controller/test_process.rb
Expand Up @@ -290,8 +290,8 @@ def binary_content
# 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!
Expand Down Expand Up @@ -435,7 +435,7 @@ def assigns(key = nil)
end

def session
@response.session
@request.session
end

def flash
Expand Down
6 changes: 3 additions & 3 deletions actionpack/test/controller/action_pack_assertions_test.rb
Expand Up @@ -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
8 changes: 4 additions & 4 deletions actionpack/test/controller/cookie_test.rb
Expand Up @@ -59,7 +59,7 @@ def test_setting_cookie_for_fourteen_days
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
Expand All @@ -71,15 +71,15 @@ def test_setting_cookie_with_http_only
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
assert_equal 2, @response.cookies.size
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 }
Expand All @@ -89,7 +89,7 @@ def test_expiring_cookie
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))
Expand Down
8 changes: 4 additions & 4 deletions actionpack/test/controller/rack_test.rb
Expand Up @@ -229,15 +229,15 @@ def test_body_should_be_rewound
class RackResponseTest < BaseRackTest
def setup
super
@response = ActionController::RackResponse.new
@response = ActionController::Response.new
end

def test_simple_output
@response.body = "Hello, World!"
@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",
Expand All @@ -258,7 +258,7 @@ def test_streaming_block
@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 = []
Expand All @@ -270,7 +270,7 @@ def test_streaming_block
class RackResponseHeadersTest < BaseRackTest
def setup
super
@response = ActionController::RackResponse.new
@response = ActionController::Response.new
@response.status = "200 OK"
end

Expand Down

2 comments on commit fda62ec

@johndouthat
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

patch.gsub(/([Aa])n Response/, ‘\1 Response’)

@josh
Copy link
Contributor Author

@josh josh commented on fda62ec Dec 20, 2008

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

commit_message.sub(“inheirt”, “inherit”) :)

Please sign in to comment.