Here are a couple more WEBrick anomolies - does anyone care??

1. If you start WEBrick without explicitly setting :BindAddress=>"0.0.0.0",
then you get a warning about the address already being in use.

  [2008-09-05 11:15:20] INFO  WEBrick 1.3.1
  [2008-09-05 11:15:20] INFO  ruby 1.8.6 (2008-03-03) [i686-linux]
  [2008-09-05 11:15:20] WARN  TCPServer Error: Address already in use - bind(2)
  [2008-09-05 11:15:20] INFO  WEBrick::HTTPServer#start: pid=8795 port=12345

2. AFAICS no clean way is provided to send a '100 continue' response when
this is required by a HTTP/1.1 client. I had to dig around into private
instance variables in WEBrick to do it. Here's an example:

  require 'webrick'
  Socket.do_not_reverse_lookup=true

  class HttpServer

    class Servlet < WEBrick::HTTPServlet::AbstractServlet
      include WEBrick
      def do_PUT(req, resp)
        raise HTTPStatus::Forbidden unless req.path == "/upload.txt"

        if req['expect'] == "100-continue" && req.http_version.to_s >= "1.1"
          # NOTE: FRIGGING WITH WEBRICK INTERNALS HERE
          req.instance_variable_get(:@socket).write "HTTP/#{resp.http_version} 100 continue\r\n\r\n"
        end

        File.open("/tmp/upload.txt", "wb") do |f|
          req.body do |chunk|
            f.write(chunk)
          end
        end
      end
    end
    
    def initialize(bind_port = 0)
      @server = WEBrick::HTTPServer.new(:Port => bind_port)
      @server.mount("/", Servlet)
      @thread = Thread.new { @server.start }
    end

    def shutdown
      if @server
        @server.stop
        @server.shutdown
        @thread.join
        @server = @thread = nil
      end
    end
  end

  s = HttpServer.new(12345)
  puts "Please upload to /upload.txt, then press Enter when finished"
  STDIN.gets
  s.shutdown

Test this code using:

  echo "hello world" | curl -v -T - http://localhost:12345/upload

Now, if you comment out the 100-continue stuff in the above code then curl
delays for a second waiting for permission to continue. Other clients may
wait longer. RFC2616 (8.2.3) just says "the client SHOULD NOT wait for an
indefinite period before sending the request body"

However a HTTP/1.1 server is *required* to implement this functionality:

        Upon receiving a request which includes an Expect request-header
        field with the "100-continue" expectation, an origin server MUST
        either respond with 100 (Continue) status and continue to read
        from the input stream, or respond with a final status code. The
        origin server MUST NOT wait for the request body before sending
        the 100 (Continue) response.

Therefore, unless I've overlooked something, I think WEBrick should expose
either a method or at least the underlying socket to enable this to be done.

Suggestion:

  class WEBrick::HTTPRequest
    def continue
      if self['expect'] == '100-continue' && @config[:HTTPVersion] >= "1.1"
        @socket.write "HTTP/#{@config[:HTTPVersion]} 100 continue\r\n\r\n"
        @header.delete('expect')
      end
    end
  end

Regards,

Brian.

P.S.
$ ruby -v
ruby 1.8.6 (2008-03-03 patchlevel 114) [i686-linux]
$ ruby -r webrick/version -e "p WEBrick::VERSION"
"1.3.1"
$ curl -V
curl 7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1
Protocols: tftp ftp telnet dict ldap ldaps http file https ftps 
Features: GSS-Negotiate IDN IPv6 Largefile NTLM SSL libz 
$