summaryrefslogtreecommitdiff
path: root/lib/webrick/httpservlet
diff options
context:
space:
mode:
authornormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-03-28 08:06:18 +0000
committernormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-03-28 08:06:18 +0000
commit4639ac8953daeed728579b809f4a4b108e0c11f7 (patch)
tree62c2dc59120a868dc526ab0b722cab4d502e5cdc /lib/webrick/httpservlet
parentd6c0b3d787b57d5c95156c25076bf222865abe5c (diff)
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 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62959 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/webrick/httpservlet')
-rw-r--r--lib/webrick/httpservlet/filehandler.rb46
1 files changed, 31 insertions, 15 deletions
diff --git a/lib/webrick/httpservlet/filehandler.rb b/lib/webrick/httpservlet/filehandler.rb
index 6e7d0ecb94..e4d892ee66 100644
--- a/lib/webrick/httpservlet/filehandler.rb
+++ b/lib/webrick/httpservlet/filehandler.rb
@@ -86,6 +86,30 @@ module WEBrick
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
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