ruby-changes:48470
From: normal <ko1@a...>
Date: Tue, 31 Oct 2017 08:56:51 +0900 (JST)
Subject: [ruby-changes:48470] normal:r60584 (trunk): webrick: support Proc objects as body responses
normal 2017-10-31 08:56:44 +0900 (Tue, 31 Oct 2017) New Revision: 60584 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=60584 Log: webrick: support Proc objects as body responses * lib/webrick/httpresponse.rb (send_body): call send_body_proc (send_body_proc): new method (class ChunkedWrapper): new class * test/webrick/test_httpresponse.rb (test_send_body_proc): new test (test_send_body_proc_chunked): ditto [Feature #855] Modified files: trunk/lib/webrick/httpresponse.rb trunk/test/webrick/test_httpresponse.rb Index: test/webrick/test_httpresponse.rb =================================================================== --- test/webrick/test_httpresponse.rb (revision 60583) +++ test/webrick/test_httpresponse.rb (revision 60584) @@ -147,6 +147,29 @@ module WEBrick https://github.com/ruby/ruby/blob/trunk/test/webrick/test_httpresponse.rb#L147 assert_equal 0, logger.messages.length end + def test_send_body_proc + @res.body = Proc.new { |out| out.write('hello') } + IO.pipe do |r, w| + @res.send_body(w) + w.close + r.binmode + assert_equal 'hello', r.read + end + assert_equal 0, logger.messages.length + end + + def test_send_body_proc_chunked + @res.body = Proc.new { |out| out.write('hello') } + @res.chunked = true + IO.pipe do |r, w| + @res.send_body(w) + w.close + r.binmode + assert_equal "5\r\nhello\r\n0\r\n\r\n", r.read + end + assert_equal 0, logger.messages.length + end + def test_set_error status = 400 message = 'missing attribute' Index: lib/webrick/httpresponse.rb =================================================================== --- lib/webrick/httpresponse.rb (revision 60583) +++ lib/webrick/httpresponse.rb (revision 60584) @@ -303,6 +303,8 @@ module WEBrick https://github.com/ruby/ruby/blob/trunk/lib/webrick/httpresponse.rb#L303 def send_body(socket) # :nodoc: if @body.respond_to? :readpartial then send_body_io(socket) + elsif @body.respond_to?(:call) then + send_body_proc(socket) else send_body_string(socket) end @@ -440,6 +442,39 @@ module WEBrick https://github.com/ruby/ruby/blob/trunk/lib/webrick/httpresponse.rb#L442 end end + 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) + @sent_size = size + end + end + + class ChunkedWrapper + def initialize(socket, resp) + @socket = socket + @resp = resp + end + + def write(buf) + return if buf.empty? + socket = @socket + @resp.instance_eval { + size = buf.bytesize + data = "#{size.to_s(16)}#{CRLF}#{buf}#{CRLF}" + _write_data(socket, data) + data.clear + @sent_size += size + } + end + alias :<< :write + end + def _send_file(output, input, offset, size) while offset > 0 sz = @buffer_size < size ? @buffer_size : size -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/