Has anyone tried streaming html/text/content from webrick? I've tried assigning an IO to the response body, but webrick is waiting for the stream to be closed first.
+1
A:
found this link by accident (http://redmine.ruby-lang.org/attachments/download/161) which contains webrick patch
# Copyright (C) 2008 Brian Candler, released under Ruby Licence.
#
# A collection of small monkey-patches to webrick.
require 'webrick'
module WEBrick
class HTTPRequest
# Generate HTTP/1.1 100 continue response. See
# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/18459
def continue
if self['expect'] == '100-continue' && @config[:HTTPVersion] >= "1.1"
@socket.write "HTTP/#{@config[:HTTPVersion]} 100 continue\r\n\r\n"
@header.delete('expect')
end
end
end
class HTTPResponse
alias :orig_setup_header :setup_header
# Correct termination of streamed HTTP/1.1 responses. See
# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/18454 and
# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/18565
def setup_header
orig_setup_header
unless chunked? || @header['content-length']
@header['connection'] = "close"
@keep_alive = false
end
end
# Allow streaming of zipfile entry. See
# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/18460
def send_body(socket)
if @body.respond_to?(:read) then send_body_io(socket)
elsif @body.respond_to?(:call) then send_body_proc(socket)
else send_body_string(socket)
end
end
# If the response body is a proc, then we invoke it and pass in
# an object which supports "write" and "<<" methods. This allows
# arbitary output streaming.
def send_body_proc(socket)
if @request_method == "HEAD"
# do nothing
elsif chunked?
@body.call(ChunkedWrapper.new(socket, self))
_write_data(socket, "0#{CRLF}#{CRLF}")
else
size = @header['content-length'].to_i
@body.call(socket) # TODO: StreamWrapper which supports offset, size
@sent_size = size
end
end
class ChunkedWrapper
def initialize(socket, resp)
@socket = socket
@resp = resp
end
def write(buf)
return if buf.empty?
data = ""
data << format("%x", buf.size) << CRLF
data << buf << CRLF
socket = @socket
@resp.instance_eval {
_write_data(socket, data)
@sent_size += buf.size
}
end
alias :<< :write
end
end
end
if RUBY_VERSION < "1.9"
old_verbose, $VERBOSE = $VERBOSE, nil
# Increase from default of 4K for efficiency, similar to
# http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/branches/ruby_1_8/lib/net/protocol.rb?r1=11708&r2=12092
# In trunk the default is 64K and can be adjusted using :InputBufferSize,
# :OutputBufferSize
WEBrick::HTTPRequest::BUFSIZE = 16384
WEBrick::HTTPResponse::BUFSIZE = 16384
$VERBOSE = old_verbose
end
to use simply pass a proc to as the response body, like so
res.body = proc { |w|
10.times do
w << Time.now.to_s
sleep(1)
end
}
woot!
alex
2009-04-19 14:25:31
A:
I would suggest against using WEBrick for anything really, it's junk. I would say try Mongrel.
I know that wasn't your question, it's just some friendly advice.
railsninja
2009-04-20 02:09:01
webrick is awesome.
alex
2009-04-21 12:30:05
Yes I guess that's true .....
railsninja
2009-04-21 13:47:46
hehehe, it's as much true as your "it's junk" :) really depends on what your needs are.
alex
2009-04-21 14:22:41
Actually thats a good point. What are your needs that specifically require WEBrick??
railsninja
2009-04-22 00:28:08
Don't /specifically/ use any of them. Use Rack ;-) That said, Rack 0.9 and over with Mongrel installed has streaming out of the box now :)
Peter Cooper
2009-05-24 01:15:58