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

ruby-changes:50773

From: normal <ko1@a...>
Date: Wed, 28 Mar 2018 17:15:37 +0900 (JST)
Subject: [ruby-changes:50773] normal:r62959 (trunk): webrick: use IO.copy_stream for multipart response

normal	2018-03-28 17:06:18 +0900 (Wed, 28 Mar 2018)

  New Revision: 62959

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=62959

  Log:
    webrick: use IO.copy_stream for multipart response
    
    Use the new Proc response body feature to generate a multipart
    range response dynamically.  We use a flat array to minimize
    object overhead as much as possible; as many ranges may fit
    into an HTTP request header.
    
    * lib/webrick/httpservlet/filehandler.rb (multipart_body): new method
      (make_partial_content): use multipart_body

  Modified files:
    trunk/lib/webrick/httpservlet/filehandler.rb
Index: lib/webrick/httpservlet/filehandler.rb
===================================================================
--- lib/webrick/httpservlet/filehandler.rb	(revision 62958)
+++ lib/webrick/httpservlet/filehandler.rb	(revision 62959)
@@ -86,6 +86,30 @@ module WEBrick https://github.com/ruby/ruby/blob/trunk/lib/webrick/httpservlet/filehandler.rb#L86
         return false
       end
 
+      # returns a lambda for webrick/httpresponse.rb send_body_proc
+      def multipart_body(body, parts, boundary, mtype, filesize)
+        lambda do |socket|
+          begin
+            begin
+              first = parts.shift
+              last = parts.shift
+              socket.write(
+                "--#{boundary}#{CRLF}" \
+                "Content-Type: #{mtype}#{CRLF}" \
+                "Content-Range: bytes #{first}-#{last}/#{filesize}#{CRLF}" \
+                "#{CRLF}"
+              )
+
+              IO.copy_stream(body, socket, last - first + 1, first)
+              socket.write(CRLF)
+            end while parts[0]
+            socket.write("--#{boundary}--#{CRLF}")
+          ensure
+            body.close
+          end
+        end
+      end
+
       def make_partial_content(req, res, filename, filesize)
         mtype = HTTPUtils::mime_type(filename, @config[:MimeTypes])
         unless ranges = HTTPUtils::parse_range_header(req['range'])
@@ -96,28 +120,20 @@ module WEBrick https://github.com/ruby/ruby/blob/trunk/lib/webrick/httpservlet/filehandler.rb#L120
           if ranges.size > 1
             time = Time.now
             boundary = "#{time.sec}_#{time.usec}_#{Process::pid}"
-            body = ''
-            ranges.each{|range|
-              first, last = prepare_range(range, filesize)
-              next if first < 0
-              io.pos = first
-              content = io.read(last-first+1)
-              body << "--" << boundary << CRLF
-              body << "Content-Type: #{mtype}" << CRLF
-              body << "Content-Range: bytes #{first}-#{last}/#{filesize}" << CRLF
-              body << CRLF
-              body << content
-              body << CRLF
+            parts = []
+            ranges.each {|range|
+              prange = prepare_range(range, filesize)
+              next if prange[0] < 0
+              parts.concat(prange)
             }
-            raise HTTPStatus::RequestRangeNotSatisfiable if body.empty?
-            body << "--" << boundary << "--" << CRLF
+            raise HTTPStatus::RequestRangeNotSatisfiable if parts.empty?
             res["content-type"] = "multipart/byteranges; boundary=#{boundary}"
             if req.http_version < '1.1'
               res['connection'] = 'close'
             else
               res.chunked = true
             end
-            res.body = body
+            res.body = multipart_body(io.dup, parts, boundary, mtype, filesize)
           elsif range = ranges[0]
             first, last = prepare_range(range, filesize)
             raise HTTPStatus::RequestRangeNotSatisfiable if first < 0

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

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