http_reader: improve robustness of header reading
authorEric Wong <normalperson@yhbt.net>
Tue, 30 Oct 2012 21:41:01 +0000 (30 21:41 +0000)
committerEric Wong <normalperson@yhbt.net>
Tue, 30 Oct 2012 21:56:18 +0000 (30 21:56 +0000)
It's possible for networks and servers to break up
even small HTTP headers.  We also better enforce the
timeout if we too too long to write the request.

lib/mogilefs/http_reader.rb

index 3afaae0..8a0337e 100644 (file)
@@ -50,17 +50,18 @@ class MogileFS::HTTPReader < MogileFS::Socket
   # body of the response.
   def self.try(path, timeout, range) # :nodoc:
     uri = URI.parse(path)
+    expire_at = Time.now + timeout
     sock = tcp(uri.host, uri.port, timeout)
     buf = "GET #{uri.request_uri} HTTP/1.0\r\n#{range}\r\n" # no chunking
     sock.timed_write(buf, timeout)
 
-    sock.timed_peek(2048, buf, timeout) or
-      raise MogileFS::InvalidResponseError, "EOF while reading header", []
+    begin
+      raise MogileFS::Timeout if Time.now > expire_at
+      sock.timed_peek(2048, buf, timeout) or
+        raise MogileFS::InvalidResponseError, "EOF while reading header", []
+    end until /\r\n\r\n/ =~ buf
 
     head, _ = buf.split(/\r\n\r\n/, 2)
-
-    # we're dealing with a seriously slow/stupid HTTP server if we can't
-    # get the header in a single recv(2) syscall.
     if ((range && head =~ %r{\AHTTP/\d+\.\d+\s+206\s*}) ||
         (!range && head =~ %r{\AHTTP/\d+\.\d+\s+200\s*})) &&
        head =~ %r{^Content-Length:\s*(\d+)}i