зеркало из https://github.com/github/ruby.git
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
This commit is contained in:
Родитель
d6c0b3d787
Коммит
4639ac8953
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче