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

move file sending to the response object

Just a slight refactor that delegates file sending to the response
object.  This gives us the advantage that if a webserver (in the future)
provides a response object that knows how to do accelerated file
serving, it can implement this method.
This commit is contained in:
Aaron Patterson 2015-10-05 16:50:37 -07:00
parent 7669844145
commit 69009f4473
6 changed files with 50 additions and 30 deletions

View file

@ -22,13 +22,13 @@ module AbstractController
# :api: public
def render(*args, &block)
options = _normalize_render(*args, &block)
self.response_body = render_to_body(options)
rendered_body = render_to_body(options)
if options[:html]
_set_html_content_type
else
_set_rendered_content_type rendered_format
end
self.response_body
self.response_body = rendered_body
end
# Raw rendering of a template to a string.

View file

@ -174,7 +174,11 @@ module ActionController
def response_body=(body)
body = [body] unless body.nil? || body.respond_to?(:each)
response.body = body
response.reset_body!
body.each { |part|
next if part.empty?
response.write part
}
super
end

View file

@ -72,31 +72,7 @@ module ActionController #:nodoc:
self.status = options[:status] || 200
self.content_type = options[:content_type] if options.key?(:content_type)
self.response_body = FileBody.new(path)
end
# Avoid having to pass an open file handle as the response body.
# Rack::Sendfile will usually intercept the response and uses
# the path directly, so there is no reason to open the file.
class FileBody #:nodoc:
attr_reader :to_path
def initialize(path)
@to_path = path
end
def body
File.binread(to_path)
end
# Stream the file's contents if Rack::Sendfile isn't present.
def each
File.open(to_path, 'rb') do |file|
while chunk = file.read(16384)
yield chunk
end
end
end
response.send_file path
end
# Sends the given binary data to the browser. This method is similar to

View file

@ -39,7 +39,7 @@ module ActionDispatch # :nodoc:
end
def []=(k,v)
if @response.committed?
if @response.sending? || @response.sent?
raise ActionDispatch::IllegalStateError, 'header already sent'
end
@ -279,6 +279,10 @@ module ActionDispatch # :nodoc:
@stream.body
end
def write(string)
@stream.write string
end
EMPTY = " "
# Allows you to manually set or override the response body.
@ -294,6 +298,40 @@ module ActionDispatch # :nodoc:
end
end
# Avoid having to pass an open file handle as the response body.
# Rack::Sendfile will usually intercept the response and uses
# the path directly, so there is no reason to open the file.
class FileBody #:nodoc:
attr_reader :to_path
def initialize(path)
@to_path = path
end
def body
File.binread(to_path)
end
# Stream the file's contents if Rack::Sendfile isn't present.
def each
File.open(to_path, 'rb') do |file|
while chunk = file.read(16384)
yield chunk
end
end
end
end
# Send the file stored at +path+ as the response body.
def send_file(path)
commit!
@stream = FileBody.new(path)
end
def reset_body!
@stream = build_buffer(self, [])
end
def body_parts
parts = []
@stream.each { |x| parts << x }

View file

@ -195,7 +195,7 @@ class SendFileTest < ActionController::TestCase
%w(file data).each do |method|
define_method "test_send_#{method}_status" do
@controller.options = { :stream => false, :status => 500 }
assert_nothing_raised { assert_not_nil process(method) }
assert_not_nil process(method)
assert_equal 500, @response.status
end

View file

@ -83,6 +83,8 @@ module ActionController
def test_headers_cannot_be_written_after_close
@response.stream.close
# we can add data until it's actually written, which happens on `each`
@response.each { |x| }
e = assert_raises(ActionDispatch::IllegalStateError) do
@response.headers['Content-Length'] = "zomg"