Index: src/future/FutureIterator.php
===================================================================
--- src/future/FutureIterator.php
+++ src/future/FutureIterator.php
@@ -233,17 +233,19 @@
         }
       }
       if ($resolve === null) {
-        if ($can_use_sockets) {
-          if ($timeout !== null) {
-            $elapsed = microtime(true) - $start;
-            if ($elapsed > $timeout) {
-              $this->isTimeout = true;
-              return;
-            } else {
-              $wait_time = $timeout - $elapsed;
-            }
+
+        // Check for a setUpdateInterval() timeout.
+        if ($timeout !== null) {
+          $elapsed = microtime(true) - $start;
+          if ($elapsed > $timeout) {
+            $this->isTimeout = true;
+            return;
+          } else {
+            $wait_time = $timeout - $elapsed;
           }
+        }
 
+        if ($can_use_sockets) {
           Future::waitForSockets($read_sockets, $write_sockets, $wait_time);
         } else {
           usleep(1000);
Index: src/future/http/HTTPSFuture.php
===================================================================
--- src/future/http/HTTPSFuture.php
+++ src/future/http/HTTPSFuture.php
@@ -3,8 +3,6 @@
 /**
  * Very basic HTTPS future.
  *
- * TODO: This class is extremely limited.
- *
  * @group futures
  */
 final class HTTPSFuture extends BaseHTTPFuture {
@@ -19,6 +17,8 @@
   private $profilerCallID;
   private $cabundle;
   private $followLocation = true;
+  private $responseBuffer = '';
+  private $responseBufferPos;
 
   /**
    * Create a temp file containing an SSL cert, and use it for this session.
@@ -263,7 +263,8 @@
 
       // Make sure we get the headers and data back.
       curl_setopt($curl, CURLOPT_HEADER, true);
-      curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+      curl_setopt($curl, CURLOPT_WRITEFUNCTION,
+        array($this, 'didReceiveDataCallback'));
 
       if ($this->followLocation) {
         curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
@@ -354,7 +355,7 @@
     }
 
     $info = self::$results[(int)$curl];
-    $result = curl_multi_getcontent($curl);
+    $result = $this->responseBuffer;
     $err_code = $info['result'];
 
     if ($err_code) {
@@ -381,4 +382,44 @@
 
     return true;
   }
+
+
+  /**
+   * Callback invoked by cURL as it reads HTTP data from the response. We save
+   * the data to a buffer.
+   */
+  public function didReceiveDataCallback($handle, $data) {
+    $this->responseBuffer .= $data;
+    return strlen($data);
+  }
+
+
+  /**
+   * Read data from the response buffer.
+   *
+   * NOTE: Like @{class:ExecFuture}, this method advances a read cursor but
+   * does not discard the data. The data will still be buffered, and it will
+   * all be returned when the future resolves. To discard the data after
+   * reading it, call @{method:discardBuffers}.
+   *
+   * @return string Response data, if available.
+   */
+  public function read() {
+    $result = substr($this->responseBuffer, $this->responseBufferPos);
+    $this->responseBufferPos = strlen($this->responseBuffer);
+    return $result;
+  }
+
+
+  /**
+   * Discard any buffered data. Normally, you call this after reading the
+   * data with @{method:read}.
+   *
+   * @return this
+   */
+  public function discardBuffers() {
+    $this->responseBuffer = '';
+    $this->responseBufferPos = 0;
+    return $this;
+  }
 }