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
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.
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
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:
# 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")))
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