[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]