diff options
author | Tanaka Akira <akr@fsij.org> | 2019-07-11 09:18:41 +0900 |
---|---|---|
committer | Tanaka Akira <akr@fsij.org> | 2019-07-11 09:18:41 +0900 |
commit | 50d85436f8f194aa78cd0e819471fe20767a5993 (patch) | |
tree | 18ce459623d72613567ace52ded44498b7a08c20 /lib/webrick | |
parent | d57ce99b7d187eb3af7749a056edeea443da93f6 (diff) | |
download | ruby-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.rb | 41 |
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 |