diff --git a/CHANGELOG.md b/CHANGELOG.md index fa15b2e10..7ce6b40cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). +## 0.13.2 (April 29th, 2021) + +### Added + +- Improve error message for specific case of `RemoteProtocolError` where server disconnects without sending a response. (Pull #313) + ## 0.13.1 (April 28th, 2021) ### Fixed diff --git a/httpcore/__init__.py b/httpcore/__init__.py index b17f3b186..91972d6dc 100644 --- a/httpcore/__init__.py +++ b/httpcore/__init__.py @@ -51,7 +51,7 @@ "WriteError", "WriteTimeout", ] -__version__ = "0.13.1" +__version__ = "0.13.2" __locals = locals() diff --git a/httpcore/_async/http11.py b/httpcore/_async/http11.py index 32bc5c41e..3b55ee2a3 100644 --- a/httpcore/_async/http11.py +++ b/httpcore/_async/http11.py @@ -167,6 +167,19 @@ async def _receive_event(self, timeout: TimeoutDict) -> H11Event: if event is h11.NEED_DATA: data = await self.socket.read(self.READ_NUM_BYTES, timeout) + + # If we feed this case through h11 we'll raise an exception like: + # + # httpcore.RemoteProtocolError: can't handle event type + # ConnectionClosed when role=SERVER and state=SEND_RESPONSE + # + # Which is accurate, but not very informative from an end-user + # perspective. Instead we handle this case distinctly and treat + # it as a ConnectError. + if data == b"" and self.h11_state.their_state == h11.SEND_RESPONSE: + msg = "Server disconnected without sending a response." + raise RemoteProtocolError(msg) + self.h11_state.receive_data(data) else: assert event is not h11.NEED_DATA diff --git a/httpcore/_sync/http11.py b/httpcore/_sync/http11.py index a805b8bad..3cd1c3995 100644 --- a/httpcore/_sync/http11.py +++ b/httpcore/_sync/http11.py @@ -167,6 +167,19 @@ def _receive_event(self, timeout: TimeoutDict) -> H11Event: if event is h11.NEED_DATA: data = self.socket.read(self.READ_NUM_BYTES, timeout) + + # If we feed this case through h11 we'll raise an exception like: + # + # httpcore.RemoteProtocolError: can't handle event type + # ConnectionClosed when role=SERVER and state=SEND_RESPONSE + # + # Which is accurate, but not very informative from an end-user + # perspective. Instead we handle this case distinctly and treat + # it as a ConnectError. + if data == b"" and self.h11_state.their_state == h11.SEND_RESPONSE: + msg = "Server disconnected without sending a response." + raise RemoteProtocolError(msg) + self.h11_state.receive_data(data) else: assert event is not h11.NEED_DATA