module Roda::RodaPlugins::Chunked::InstanceMethods
def chunked(template, opts=OPTS, &block)
Render a response to the user in chunks. See Chunked for
def chunked(template, opts=OPTS, &block) unless defined?(@_chunked) @_chunked = !self.opts[:force_chunked_encoding] || @_request.http_version == "HTTP/1.1" end if block delay(&block) end unless @_chunked # If chunking is disabled, do a normal rendering of the view. run_delayed_blocks return view(template, opts) end if template.is_a?(Hash) if opts.empty? opts = template else opts = Hash[opts].merge!(template) end end # Hack so that the arguments don't need to be passed # through the response and body objects. @_each_chunk_args = [template, opts] res = response headers = res.headers if chunk_headers = self.opts[:chunk_headers] headers.merge!(chunk_headers) end if self.opts[:force_chunked_encoding] res[RodaResponseHeaders::TRANSFER_ENCODING] = 'chunked' body = Body.new(self) else body = StreamBody.new(self) end throw :halt, res.finish_with_body(body) end
def delay(&block)
Delay the execution of the block until right before the
def delay(&block) raise RodaError, "must pass a block to Roda#delay" unless block (@_delays ||= []) << block end
def each_chunk
def each_chunk response.body.each{|s| yield s} template, opts = @_each_chunk_args # Use a lambda for the flusher, so that a call to flush # by a template can result in this method yielding a chunk # of the response. @_flusher = lambda do yield @_out_buf @_out_buf = String.new end if layout_opts = view_layout_opts(opts) @_out_buf = render_template(layout_opts) do flush run_delayed_blocks yield opts[:content] || render_template(template, opts) nil end else run_delayed_blocks yield view(template, opts) end flush rescue => e handle_chunk_error(e) end
def flush
is a no-op, so flush can be used inside views without breaking
Call the flusher if one is defined. If one is not defined, this
def flush @_flusher.call if @_flusher end
def handle_chunk_error(e)
def handle_chunk_error(e) raise e end
def no_chunk!
Disable chunking for the current request. Mostly useful when
def no_chunk! @_chunked = false end
def run_delayed_blocks
def run_delayed_blocks return unless @_delays @_delays.each(&:call) end
def view(*a)
If chunking by default, call chunked if it hasn't yet been
def view(*a) if opts[:chunk_by_default] && !defined?(@_chunked) && !defined?(yield) chunked(*a) else super end end