aboutsummaryrefslogtreecommitdiffstats
path: root/lib/webrick
diff options
context:
space:
mode:
authorTanaka Akira <akr@fsij.org>2019-07-11 09:18:41 +0900
committerTanaka Akira <akr@fsij.org>2019-07-11 09:18:41 +0900
commit50d85436f8f194aa78cd0e819471fe20767a5993 (patch)
tree18ce459623d72613567ace52ded44498b7a08c20 /lib/webrick
parentd57ce99b7d187eb3af7749a056edeea443da93f6 (diff)
downloadruby-50d85436f8f194aa78cd0e819471fe20767a5993.tar.gz
WEBrick::HTTPResponse create tempfile if required.
WEBrick::HTTPProxyServer implementes HTTP proxy using WEBrick and Net::HTTP. WEBrick accepts HTTP/1.0 clients and Net::HTTP uses always HTTP/1.1. However HTTP/1.1 supports chunked transfer coding HTTP/1.0 doesn't. Chunked transfer coding doesn't require that content-length before the content is sent. But non-chunked transfer coding require content-length before the content is sent. So, when HTTP/1.0 clients connects WEBrick::HTTPProxyServer and origin server returns chunked response, WEBrick::HTTPProxyServer needs to store whole content to know the length of it. This patch do it using tempfile.
Diffstat (limited to 'lib/webrick')
-rw-r--r--lib/webrick/httpresponse.rb41
1 files changed, 39 insertions, 2 deletions
diff --git a/lib/webrick/httpresponse.rb b/lib/webrick/httpresponse.rb
index f206a05ce9..62d8056cf7 100644
--- a/lib/webrick/httpresponse.rb
+++ b/lib/webrick/httpresponse.rb
@@ -113,6 +113,7 @@ module WEBrick
@chunked = false
@filename = nil
@sent_size = 0
+ @bodytempfile = nil
end
##
@@ -253,7 +254,10 @@ module WEBrick
elsif %r{^multipart/byteranges} =~ @header['content-type']
@header.delete('content-length')
elsif @header['content-length'].nil?
- unless @body.is_a?(IO)
+ if @body.respond_to? :readpartial
+ elsif @body.respond_to? :call
+ make_body_tempfile
+ else
@header['content-length'] = (@body ? @body.bytesize : 0).to_s
end
end
@@ -282,6 +286,33 @@ module WEBrick
end
end
+ def make_body_tempfile # :nodoc:
+ return if @bodytempfile
+ bodytempfile = Tempfile.create("webrick")
+ if @body.nil?
+ # nothing
+ elsif @body.respond_to? :readpartial
+ IO.copy_stream(@body, bodytempfile)
+ @body.close
+ elsif @body.respond_to? :call
+ @body.call(bodytempfile)
+ else
+ bodytempfile.write @body
+ end
+ bodytempfile.rewind
+ @body = @bodytempfile = bodytempfile
+ @header['content-length'] = bodytempfile.stat.size.to_s
+ end
+
+ def remove_body_tempfile # :nodoc:
+ if @bodytempfile
+ @bodytempfile.close
+ File.unlink @bodytempfile.path
+ @bodytempfile = nil
+ end
+ end
+
+
##
# Sends the headers on +socket+
@@ -445,6 +476,7 @@ module WEBrick
ensure
@body.close
end
+ remove_body_tempfile
end
def send_body_string(socket)
@@ -477,7 +509,12 @@ module WEBrick
socket.write("0#{CRLF}#{CRLF}")
else
size = @header['content-length'].to_i
- @body.call(socket)
+ if @bodytempfile
+ @bodytempfile.rewind
+ IO.copy_stream(@bodytempfile, socket)
+ else
+ @body.call(socket)
+ end
@sent_size = size
end
end