1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Return body parts directly to Rack rather than building a response string ourselves. Allows Rack middleware to orchestrate response building.

This commit is contained in:
Jeremy Kemper 2009-03-12 21:47:34 -07:00
parent c8c2b3820e
commit 91d2740595
6 changed files with 44 additions and 27 deletions

View file

@ -984,6 +984,7 @@ module ActionController #:nodoc:
# of sending it as the response body to the browser.
def render_to_string(options = nil, &block) #:doc:
render(options, &block)
response.body
ensure
response.content_type = nil
erase_render_results
@ -1020,7 +1021,7 @@ module ActionController #:nodoc:
# Clears the rendered results, allowing for another render to be performed.
def erase_render_results #:nodoc:
response.body = nil
response.body = []
@performed_render = false
end
@ -1247,13 +1248,12 @@ module ActionController #:nodoc:
response.status = interpret_status(status || DEFAULT_RENDER_STATUS_CODE)
if append_response
response.body ||= ''
response.body << text.to_s
response.body_parts << text.to_s
else
response.body = case text
when Proc then text
when nil then " " # Safari doesn't pass the headers of the return if the response is zero length
else text.to_s
when Proc then text
when nil then [" "] # Safari doesn't pass the headers of the return if the response is zero length
else [text.to_s]
end
end
end

View file

@ -332,11 +332,13 @@ module ActionController
@cookies[name] = value
end
@body = ""
if body.is_a?(String)
@body << body
@body_parts = [body]
@body = body
else
body.each { |part| @body << part }
@body_parts = []
body.each { |part| @body_parts << part.to_s }
@body = @body_parts.join
end
if @controller = ActionController::Base.last_instantiation
@ -349,7 +351,7 @@ module ActionController
@response = Response.new
@response.status = status.to_s
@response.headers.replace(@headers)
@response.body = @body
@response.body = @body_parts
end
# Decorate the response with the standard behavior of the

View file

@ -40,16 +40,30 @@ module ActionController # :nodoc:
delegate :default_charset, :to => 'ActionController::Base'
def initialize
@status = 200
super
@header = Rack::Utils::HeaderHash.new(DEFAULT_HEADERS)
@writer = lambda { |x| @body << x }
@block = nil
@body = "",
@session, @assigns = [], []
end
def body
str = ''
each { |part| str << part.to_s }
str
end
def body=(body)
@body =
if body.is_a?(String)
[body]
else
body
end
end
def body_parts
@body
end
def location; headers['Location'] end
def location=(url) headers['Location'] = url end
@ -152,7 +166,7 @@ module ActionController # :nodoc:
@writer = lambda { |x| callback.call(x) }
@body.call(self, self)
elsif @body.is_a?(String)
@body.each_line(&callback)
callback.call(@body)
else
@body.each(&callback)
end
@ -162,7 +176,8 @@ module ActionController # :nodoc:
end
def write(str)
@writer.call str.to_s
str = str.to_s
@writer.call str
str
end
@ -186,7 +201,7 @@ module ActionController # :nodoc:
if request && request.etag_matches?(etag)
self.status = '304 Not Modified'
self.body = ''
self.body = []
end
set_conditional_cache_control!
@ -195,7 +210,7 @@ module ActionController # :nodoc:
def nonempty_ok_response?
ok = !status || status.to_s[0..2] == '200'
ok && body.is_a?(String) && !body.empty?
ok && !body_parts.respond_to?(:call) && body_parts.any?
end
def set_conditional_cache_control!
@ -216,8 +231,8 @@ module ActionController # :nodoc:
headers.delete('Content-Length')
elsif length = headers['Content-Length']
headers['Content-Length'] = length.to_s
elsif !body.respond_to?(:call) && (!status || status.to_s[0..2] != '304')
headers["Content-Length"] = (body.respond_to?(:bytesize) ? body.bytesize : body.size).to_s
elsif !body_parts.respond_to?(:call) && (!status || status.to_s[0..2] != '304')
headers["Content-Length"] = Rack::Utils.bytesize(body).to_s
end
end

View file

@ -258,11 +258,11 @@ module ActionController #:nodoc:
# Returns binary content (downloadable file), converted to a String
def binary_content
raise "Response body is not a Proc: #{body.inspect}" unless body.kind_of?(Proc)
raise "Response body is not a Proc: #{body_parts.inspect}" unless body_parts.kind_of?(Proc)
require 'stringio'
sio = StringIO.new
body.call(self, sio)
body_parts.call(self, sio)
sio.rewind
sio.read

View file

@ -258,7 +258,7 @@ class RackResponseTest < BaseRackTest
}, headers)
parts = []
body.each { |part| parts << part }
body.each { |part| parts << part.to_s }
assert_equal ["0", "1", "2", "3", "4"], parts
end
end

View file

@ -44,12 +44,12 @@ class SendFileTest < ActionController::TestCase
response = nil
assert_nothing_raised { response = process('file') }
assert_not_nil response
assert_kind_of Proc, response.body
assert_kind_of Proc, response.body_parts
require 'stringio'
output = StringIO.new
output.binmode
assert_nothing_raised { response.body.call(response, output) }
assert_nothing_raised { response.body_parts.call(response, output) }
assert_equal file_data, output.string
end