From 50d85436f8f194aa78cd0e819471fe20767a5993 Mon Sep 17 00:00:00 2001 From: Tanaka Akira Date: Thu, 11 Jul 2019 09:18:41 +0900 Subject: 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. --- lib/webrick/httpresponse.rb | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) (limited to 'lib/webrick/httpresponse.rb') 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 -- cgit v1.2.3