Project

General

Profile

Feature #855 ยป webrick-patches.rb

Monkey patches to webrick - candlerb (Brian Candler), 12/11/2008 07:08 PM

 
1
# Copyright (C) 2008 Brian Candler, released under Ruby Licence.
2
#
3
# A collection of small monkey-patches to webrick.
4

    
5
require 'webrick'
6

    
7
module WEBrick
8

    
9
  class HTTPRequest
10
    # Generate HTTP/1.1 100 continue response. See
11
    # http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/18459
12
    def continue
13
      if self['expect'] == '100-continue' && @config[:HTTPVersion] >= "1.1"
14
        @socket.write "HTTP/#{@config[:HTTPVersion]} 100 continue\r\n\r\n"
15
        @header.delete('expect')
16
      end
17
    end
18
  end
19

    
20
  class HTTPResponse
21
    alias :orig_setup_header :setup_header
22
    # Correct termination of streamed HTTP/1.1 responses. See
23
    # http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/18454 and
24
    # http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/18565
25
    def setup_header
26
      orig_setup_header
27
      unless chunked? || @header['content-length']
28
        @header['connection'] = "close"
29
        @keep_alive = false
30
      end
31
    end
32

    
33
    # Allow streaming of zipfile entry. See
34
    # http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/18460
35
    def send_body(socket)
36
      if @body.respond_to?(:read) then send_body_io(socket)
37
      elsif @body.respond_to?(:call) then send_body_proc(socket)
38
      else send_body_string(socket)
39
      end
40
    end
41

    
42
    # If the response body is a proc, then we invoke it and pass in
43
    # an object which supports "write" and "<<" methods. This allows
44
    # arbitary output streaming.
45
    def send_body_proc(socket)
46
      if @request_method == "HEAD"
47
        # do nothing
48
      elsif chunked?
49
        @body.call(ChunkedWrapper.new(socket, self))
50
        _write_data(socket, "0#{CRLF}#{CRLF}")
51
      else
52
        size = @header['content-length'].to_i
53
        @body.call(socket)   # TODO: StreamWrapper which supports offset, size
54
        @sent_size = size
55
      end
56
    end
57
          
58
    class ChunkedWrapper
59
      def initialize(socket, resp)
60
        @socket = socket
61
        @resp = resp
62
      end
63
      def write(buf)
64
        return if buf.empty?
65
        data = ""
66
        data << format("%x", buf.size) << CRLF
67
        data << buf << CRLF
68
        socket = @socket
69
        @resp.instance_eval {
70
          _write_data(socket, data)
71
          @sent_size += buf.size
72
        }
73
      end
74
      alias :<< :write
75
    end
76
  end
77
end
78

    
79
if RUBY_VERSION < "1.9"
80
  old_verbose, $VERBOSE = $VERBOSE, nil
81
  # Increase from default of 4K for efficiency, similar to
82
  # http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/branches/ruby_1_8/lib/net/protocol.rb?r1=11708&r2=12092
83
  # In trunk the default is 64K and can be adjusted using :InputBufferSize,
84
  # :OutputBufferSize
85
  WEBrick::HTTPRequest::BUFSIZE = 16384
86
  WEBrick::HTTPResponse::BUFSIZE = 16384
87
  $VERBOSE = old_verbose
88
end