diff --git a/aiohttp/web_protocol.py b/aiohttp/web_protocol.py index b9ee34746ad..795e574b8ae 100644 --- a/aiohttp/web_protocol.py +++ b/aiohttp/web_protocol.py @@ -18,7 +18,7 @@ from .tcp_helpers import tcp_cork, tcp_keepalive, tcp_nodelay from .web_exceptions import HTTPException from .web_request import BaseRequest -from .web_response import Response +from .web_response import Response, StreamResponse __all__ = ('RequestHandler', 'RequestPayloadError', 'PayloadAccessError') @@ -346,6 +346,7 @@ async def start(self): handler = self._task_handler manager = self._manager keepalive_timeout = self._keepalive_timeout + resp = None while not self._force_close: if not self._messages: @@ -389,6 +390,13 @@ async def start(self): "please raise the exception instead", DeprecationWarning) + if self.debug: + if not isinstance(resp, StreamResponse): + self.log_debug("Possibly missing return " + "statement on request handler") + raise RuntimeError("Web-handler should return " + "a response instance, " + "got {!r}".format(resp)) await resp.prepare(request) await resp.write_eof() @@ -438,7 +446,7 @@ async def start(self): self.log_exception('Unhandled exception', exc_info=exc) self.force_close() finally: - if self.transport is None: + if self.transport is None and resp is not None: self.log_debug('Ignored premature client disconnection.') elif not self._force_close: if self._keepalive and not self._close: diff --git a/tests/test_web_protocol.py b/tests/test_web_protocol.py index 6e00d8dca49..47536862177 100644 --- a/tests/test_web_protocol.py +++ b/tests/test_web_protocol.py @@ -517,6 +517,32 @@ async def cancel(): assert log.debug.called +async def test_handle_none_response(make_srv, transport, request_handler): + loop = asyncio.get_event_loop() + log = mock.Mock() + + srv = make_srv(logger=log, debug=True) + srv.connection_made(transport) + + handle = mock.Mock() + handle.return_value = loop.create_future() + handle.return_value.set_result(None) + request_handler.side_effect = handle + + srv.data_received( + b'GET / HTTP/1.0\r\n' + b'Content-Length: 10\r\n' + b'Host: example.com\r\n\r\n') + + assert srv._task_handler + + await asyncio.sleep(0, loop=loop) + await srv._task_handler + assert request_handler.called + log.debug.assert_called_with("Possibly missing return " + "statement on request handler") + + async def test_handle_cancelled(make_srv, transport) -> None: log = mock.Mock()