From c58734056827d5855bae9b82c1600f3a8d83d6ae Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Thu, 22 Jan 2015 15:51:10 -0800 Subject: [PATCH] do not swallow websocket reader exceptions #255 --- CHANGES.txt | 7 +++-- aiohttp/web.py | 10 +++++++ tests/test_web_websocket.py | 56 +++++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 2 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 52e51c09bad..6941595be8a 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,12 +1,15 @@ CHANGES ======= -0.15.0 (Unreleased) +0.14.2 (Unreleased) ------------------- +- Do not swallow websocket reader exceptions #255 + - web.Request's read, text, json are memorized #250 -0.14.0 (15/01/2014) + +0.14.1 (15/01/2014) ------------------- - HttpMessage._add_default_headers does not overwrite existing headers #216 diff --git a/aiohttp/web.py b/aiohttp/web.py index bd49b55a1de..044efd9bd02 100644 --- a/aiohttp/web.py +++ b/aiohttp/web.py @@ -829,6 +829,16 @@ def wait_closed(self): raise RuntimeError('Call .start() first') yield from self._closing_fut + @asyncio.coroutine + def write_eof(self): + if self._eof_sent: + return + if self._resp_impl is None: + raise RuntimeError("Response has not been started") + + yield from self.wait_closed() + self._eof_sent = True + @asyncio.coroutine def receive_msg(self): if self._reader is None: diff --git a/tests/test_web_websocket.py b/tests/test_web_websocket.py index 4d3c75083aa..0e26290420e 100644 --- a/tests/test_web_websocket.py +++ b/tests/test_web_websocket.py @@ -257,3 +257,59 @@ def go(): yield from ws.wait_closed() self.loop.run_until_complete(go()) + + def test_write_eof_not_started(self): + + @asyncio.coroutine + def go(): + ws = WebSocketResponse() + with self.assertRaises(RuntimeError): + yield from ws.write_eof() + + self.loop.run_until_complete(go()) + + def test_write_eof_idempotent(self): + req = self.make_request('GET', '/') + ws = WebSocketResponse() + ws.start(req) + ws._closing_fut.set_result(1) + + @asyncio.coroutine + def go(): + yield from ws.write_eof() + yield from ws.write_eof() + yield from ws.write_eof() + + self.loop.run_until_complete(go()) + + def test_write_eof_exception(self): + req = self.make_request('GET', '/') + ws = WebSocketResponse() + ws.start(req) + ws._closing_fut.set_exception(ValueError()) + + @asyncio.coroutine + def go(): + with self.assertRaises(ValueError): + yield from ws.write_eof() + + self.loop.run_until_complete(go()) + + def test_receive_msg_exc_in_reader(self): + req = self.make_request('GET', '/') + ws = WebSocketResponse() + ws.start(req) + + exc = ValueError() + res = asyncio.Future(loop=self.loop) + res.set_exception(exc) + ws._reader.read.return_value = res + + @asyncio.coroutine + def go(): + with self.assertRaises(ValueError): + yield from ws.receive_msg() + + self.assertIs(ws._closing_fut.exception(), exc) + + self.loop.run_until_complete(go())