]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Add read_until_close method to IOStream and use it in SimpleAsyncHTTPClient.
authorBen Darnell <ben@bendarnell.com>
Sun, 26 Jun 2011 19:27:54 +0000 (12:27 -0700)
committerBen Darnell <ben@bendarnell.com>
Sun, 26 Jun 2011 19:27:54 +0000 (12:27 -0700)
tornado/iostream.py
tornado/simple_httpclient.py
tornado/test/iostream_test.py
website/sphinx/releases/next.rst

index cebd6f41720ef53b9249cc4513583b43b549b939..fdb1e28d3d279c0a8982916d718244239835a817 100644 (file)
@@ -90,6 +90,7 @@ class IOStream(object):
         self._write_buffer_frozen = False
         self._read_delimiter = None
         self._read_bytes = None
+        self._read_until_close = False
         self._read_callback = None
         self._write_callback = None
         self._close_callback = None
@@ -152,6 +153,19 @@ class IOStream(object):
                 break
         self._add_io_state(self.io_loop.READ)
 
+    def read_until_close(self, callback):
+        """Reads all data from the socket until it is closed.
+
+        Subject to ``max_buffer_size`` limit from `IOStream` constructor.
+        """
+        assert not self._read_callback, "Already reading"
+        if self.closed():
+            self._run_callback(callback, self._consume(self._read_buffer_size))
+            return
+        self._read_until_close = True
+        self._read_callback = stack_context.wrap(callback)
+        self._add_io_state(self.io_loop.READ)
+
     def write(self, data, callback=None):
         """Write the given data to this stream.
 
@@ -173,6 +187,12 @@ class IOStream(object):
     def close(self):
         """Close this stream."""
         if self.socket is not None:
+            if self._read_until_close:
+                callback = self._read_callback
+                self._read_callback = None
+                self._read_until_close = False
+                self._run_callback(callback,
+                                   self._consume(self._read_buffer_size))
             self.io_loop.remove_handler(self.socket.fileno())
             self.socket.close()
             self.socket = None
index a8b90af1a9fb4d0eee8aafe4a999af45d17ffddf..5d0886790b3d088485029bf792847bab7e505e1e 100644 (file)
@@ -299,8 +299,7 @@ class _HTTPConnection(object):
             self.stream.read_bytes(int(self.headers["Content-Length"]),
                                    self._on_body)
         else:
-            raise Exception("No Content-length or chunked encoding, "
-                            "don't know how to read %s", self.request.url)
+            self.stream.read_until_close(self._on_body)
 
     def _on_body(self, data):
         if self._timeout is not None:
index f7d462da72ce2cee1bc623a5b33bafa4c0ddfc8f..72df5f0a0794c57f745215b3f2c9bdfd06111d7a 100644 (file)
@@ -56,3 +56,14 @@ class TestIOStream(AsyncHTTPTestCase, LogTrapTestCase):
         # flag.
         response = self.fetch("/", headers={"Connection": "close"})
         response.rethrow()
+
+    def test_read_until_close(self):
+        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
+        s.connect(("localhost", self.get_http_port()))
+        stream = IOStream(s, io_loop=self.io_loop)
+        stream.write(b("GET / HTTP/1.0\r\n\r\n"))
+        
+        stream.read_until_close(self.stop)
+        data = self.wait()
+        self.assertTrue(data.startswith(b("HTTP/1.0 200")))
+        self.assertTrue(data.endswith(b("Hello")))
index 787aad3c8f5df1b01386b5ae5a31f8e3bdd43079..b3ac42a20c81ab76c8b0b3e76cc2d10ec650da3c 100644 (file)
@@ -4,10 +4,16 @@ What's new in the next release of Tornado
 In progress
 -----------
 
+New features
+~~~~~~~~~~~~
+
+* New method `tornado.iostream.IOStream.read_until_close`
+
 Bug fixes
 ~~~~~~~~~
 
 * `HTTPServer`: fixed exception at startup when ``socket.AI_ADDRCONFIG`` is
   not available, as on Windows XP
 * `tornado.websocket`: now works on Python 3
-
+* `SimpleAsyncHTTPClient`: now works with HTTP 1.0 servers that don't send
+  a Content-Length header