mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Body... wanna *stream* my body? Body... such a thrill my body!
Added stream as class level method to make it explicit when to stream. Render also accepts :stream as option.
This commit is contained in:
parent
7a152ab012
commit
389d15ef13
5 changed files with 122 additions and 0 deletions
|
@ -31,6 +31,7 @@ module ActionController
|
|||
autoload :Rescue
|
||||
autoload :Responder
|
||||
autoload :SessionManagement
|
||||
autoload :Streaming
|
||||
autoload :Testing
|
||||
autoload :UrlFor
|
||||
end
|
||||
|
|
|
@ -199,6 +199,7 @@ module ActionController
|
|||
Flash,
|
||||
RequestForgeryProtection,
|
||||
ForceSSL,
|
||||
Streaming,
|
||||
DataStreaming,
|
||||
RecordIdentifier,
|
||||
HttpAuthentication::Basic::ControllerMethods,
|
||||
|
|
57
actionpack/lib/action_controller/metal/streaming.rb
Normal file
57
actionpack/lib/action_controller/metal/streaming.rb
Normal file
|
@ -0,0 +1,57 @@
|
|||
require 'active_support/core_ext/file/path'
|
||||
require 'rack/chunked'
|
||||
|
||||
module ActionController #:nodoc:
|
||||
# Methods for sending streaming templates back to the client.
|
||||
module Streaming
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
include AbstractController::Rendering
|
||||
attr_internal :stream
|
||||
|
||||
module ClassMethods
|
||||
# Render streaming templates. It accepts :only, :except, :if and :unless as options
|
||||
# to specify when to stream, as in ActionController filters.
|
||||
def stream(options={})
|
||||
if defined?(Fiber)
|
||||
before_filter :_stream_filter, options
|
||||
else
|
||||
raise "You cannot use streaming if Fiber is not available."
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# Mark following render calls as streaming.
|
||||
def _stream_filter #:nodoc:
|
||||
self.stream = true
|
||||
end
|
||||
|
||||
# Consider the stream option when normalazing options.
|
||||
def _normalize_options(options) #:nodoc:
|
||||
super
|
||||
options[:stream] = self.stream unless options.key?(:stream)
|
||||
end
|
||||
|
||||
# Set proper cache control and transfer encoding when streaming
|
||||
def _process_options(options) #:nodoc:
|
||||
super
|
||||
if options[:stream]
|
||||
headers["Cache-Control"] ||= "no-cache"
|
||||
headers["Transfer-Encoding"] = "chunked"
|
||||
headers.delete("Content-Length")
|
||||
end
|
||||
end
|
||||
|
||||
# Call render_to_body if we are streaming instead of usual +render+.
|
||||
def _render_template(options) #:nodoc:
|
||||
if options.delete(:stream)
|
||||
Rack::Chunked::Body.new view_context.render_body(options)
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -2,6 +2,7 @@ module ActionView
|
|||
module CompiledTemplates #:nodoc:
|
||||
# holds compiled template code
|
||||
end
|
||||
|
||||
# = Action View Context
|
||||
#
|
||||
# Action View contexts are supplied to Action Controller to render template.
|
||||
|
|
62
actionpack/test/controller/new_base/render_streaming_test.rb
Normal file
62
actionpack/test/controller/new_base/render_streaming_test.rb
Normal file
|
@ -0,0 +1,62 @@
|
|||
require 'abstract_unit'
|
||||
|
||||
module RenderStreaming
|
||||
class BasicController < ActionController::Base
|
||||
self.view_paths = [ActionView::FixtureResolver.new(
|
||||
"render_streaming/basic/hello_world.html.erb" => "Hello world",
|
||||
"layouts/application.html.erb" => "<%= yield %>, I'm here!"
|
||||
)]
|
||||
|
||||
layout "application"
|
||||
stream :only => :hello_world
|
||||
|
||||
def hello_world
|
||||
end
|
||||
|
||||
def explicit
|
||||
render :action => "hello_world", :stream => true
|
||||
end
|
||||
|
||||
def no_layout
|
||||
render :action => "hello_world", :stream => true, :layout => false
|
||||
end
|
||||
|
||||
def explicit_cache
|
||||
headers["Cache-Control"] = "private"
|
||||
render :action => "hello_world", :stream => true
|
||||
end
|
||||
end
|
||||
|
||||
class StreamingTest < Rack::TestCase
|
||||
test "rendering with streaming enabled at the class level" do
|
||||
get "/render_streaming/basic/hello_world"
|
||||
assert_body "b\r\nHello world\r\nb\r\n, I'm here!\r\n0\r\n\r\n"
|
||||
assert_streaming!
|
||||
end
|
||||
|
||||
test "rendering with streaming given to render" do
|
||||
get "/render_streaming/basic/explicit"
|
||||
assert_body "b\r\nHello world\r\nb\r\n, I'm here!\r\n0\r\n\r\n"
|
||||
assert_streaming!
|
||||
end
|
||||
|
||||
test "rendering with streaming do not override explicit cache control given to render" do
|
||||
get "/render_streaming/basic/explicit_cache"
|
||||
assert_body "b\r\nHello world\r\nb\r\n, I'm here!\r\n0\r\n\r\n"
|
||||
assert_streaming! "private"
|
||||
end
|
||||
|
||||
test "rendering with streaming no layout" do
|
||||
get "/render_streaming/basic/no_layout"
|
||||
assert_body "b\r\nHello world\r\n0\r\n\r\n"
|
||||
assert_streaming!
|
||||
end
|
||||
|
||||
def assert_streaming!(cache="no-cache")
|
||||
assert_status 200
|
||||
assert_equal nil, headers["Content-Length"]
|
||||
assert_equal "chunked", headers["Transfer-Encoding"]
|
||||
assert_equal cache, headers["Cache-Control"]
|
||||
end
|
||||
end if defined?(Fiber)
|
||||
end
|
Loading…
Reference in a new issue