From f4240b64735ce5cafcfed24b6417c16d61a034df Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Sun, 2 Aug 2020 12:59:24 +0100 Subject: [PATCH] Add LocalProtocolError, RemoteProtocolError (#129) * Add LocalProtocolError, RemoteProtocolError * Fix indentation --- httpcore/__init__.py | 4 ++++ httpcore/_async/connection_pool.py | 4 +++- httpcore/_async/http11.py | 7 ++++--- httpcore/_async/http2.py | 4 ++-- httpcore/_exceptions.py | 8 ++++++++ httpcore/_sync/connection_pool.py | 4 +++- httpcore/_sync/http11.py | 7 ++++--- httpcore/_sync/http2.py | 4 ++-- 8 files changed, 30 insertions(+), 12 deletions(-) diff --git a/httpcore/__init__.py b/httpcore/__init__.py index 084dd30c..a1f80ab3 100644 --- a/httpcore/__init__.py +++ b/httpcore/__init__.py @@ -8,6 +8,8 @@ NetworkError, PoolTimeout, ProtocolError, + RemoteProtocolError, + LocalProtocolError, ProxyError, ReadError, ReadTimeout, @@ -39,6 +41,8 @@ "ReadError", "WriteError", "CloseError", + "LocalProtocolError", + "RemoteProtocolError", "UnsupportedProtocol", ] __version__ = "0.9.1" diff --git a/httpcore/_async/connection_pool.py b/httpcore/_async/connection_pool.py index b90e136d..2c7101cc 100644 --- a/httpcore/_async/connection_pool.py +++ b/httpcore/_async/connection_pool.py @@ -2,7 +2,7 @@ from typing import AsyncIterator, Callable, Dict, List, Optional, Set, Tuple from .._backends.auto import AsyncLock, AsyncSemaphore, AutoBackend -from .._exceptions import PoolTimeout, UnsupportedProtocol +from .._exceptions import PoolTimeout, LocalProtocolError, UnsupportedProtocol from .._threadlock import ThreadLock from .._types import URL, Headers, Origin, TimeoutDict from .._utils import get_logger, origin_to_url_string, url_to_origin @@ -127,6 +127,8 @@ async def request( if url[0] not in (b"http", b"https"): scheme = url[0].decode("latin-1") raise UnsupportedProtocol(f"Unsupported URL protocol {scheme!r}") + if not url[1]: + raise LocalProtocolError("Missing hostname in URL.") origin = url_to_origin(url) diff --git a/httpcore/_async/http11.py b/httpcore/_async/http11.py index 80204075..e513cdd6 100644 --- a/httpcore/_async/http11.py +++ b/httpcore/_async/http11.py @@ -4,7 +4,7 @@ import h11 from .._backends.auto import AsyncSocketStream -from .._exceptions import ProtocolError, map_exceptions +from .._exceptions import RemoteProtocolError, LocalProtocolError, map_exceptions from .._types import URL, Headers, TimeoutDict from .._utils import get_logger from .base import AsyncByteStream, ConnectionState @@ -91,7 +91,8 @@ async def _send_request( """ logger.trace("send_request method=%r url=%r headers=%s", method, url, headers) _scheme, _host, _port, target = url - event = h11.Request(method=method, target=target, headers=headers) + with map_exceptions({h11.LocalProtocolError: LocalProtocolError}): + event = h11.Request(method=method, target=target, headers=headers) await self._send_event(event, timeout) async def _send_request_body( @@ -151,7 +152,7 @@ async def _receive_event(self, timeout: TimeoutDict) -> H11Event: Read a single `h11` event, reading more data from the network if needed. """ while True: - with map_exceptions({h11.RemoteProtocolError: ProtocolError}): + with map_exceptions({h11.RemoteProtocolError: RemoteProtocolError}): event = self.h11_state.next_event() if event is h11.NEED_DATA: diff --git a/httpcore/_async/http2.py b/httpcore/_async/http2.py index e13d9f38..af5b9eed 100644 --- a/httpcore/_async/http2.py +++ b/httpcore/_async/http2.py @@ -9,7 +9,7 @@ from h2.settings import SettingCodes, Settings from .._backends.auto import AsyncLock, AsyncSemaphore, AsyncSocketStream, AutoBackend -from .._exceptions import PoolTimeout, ProtocolError +from .._exceptions import PoolTimeout, RemoteProtocolError from .._types import URL, Headers, TimeoutDict from .._utils import get_logger from .base import AsyncByteStream, ConnectionState, NewConnectionRequired @@ -215,7 +215,7 @@ async def receive_events(self, timeout: TimeoutDict) -> None: logger.trace("receive_event stream_id=%r event=%s", event_stream_id, event) if hasattr(event, "error_code"): - raise ProtocolError(event) + raise RemoteProtocolError(event) if event_stream_id in self.events: self.events[event_stream_id].append(event) diff --git a/httpcore/_exceptions.py b/httpcore/_exceptions.py index 26913239..93b03118 100644 --- a/httpcore/_exceptions.py +++ b/httpcore/_exceptions.py @@ -21,6 +21,14 @@ class ProtocolError(Exception): pass +class RemoteProtocolError(ProtocolError): + pass + + +class LocalProtocolError(ProtocolError): + pass + + class ProxyError(Exception): pass diff --git a/httpcore/_sync/connection_pool.py b/httpcore/_sync/connection_pool.py index 44a14b6d..9ac8456a 100644 --- a/httpcore/_sync/connection_pool.py +++ b/httpcore/_sync/connection_pool.py @@ -2,7 +2,7 @@ from typing import Iterator, Callable, Dict, List, Optional, Set, Tuple from .._backends.auto import SyncLock, SyncSemaphore, SyncBackend -from .._exceptions import PoolTimeout, UnsupportedProtocol +from .._exceptions import PoolTimeout, LocalProtocolError, UnsupportedProtocol from .._threadlock import ThreadLock from .._types import URL, Headers, Origin, TimeoutDict from .._utils import get_logger, origin_to_url_string, url_to_origin @@ -127,6 +127,8 @@ def request( if url[0] not in (b"http", b"https"): scheme = url[0].decode("latin-1") raise UnsupportedProtocol(f"Unsupported URL protocol {scheme!r}") + if not url[1]: + raise LocalProtocolError("Missing hostname in URL.") origin = url_to_origin(url) diff --git a/httpcore/_sync/http11.py b/httpcore/_sync/http11.py index 537b55ab..2235ad26 100644 --- a/httpcore/_sync/http11.py +++ b/httpcore/_sync/http11.py @@ -4,7 +4,7 @@ import h11 from .._backends.auto import SyncSocketStream -from .._exceptions import ProtocolError, map_exceptions +from .._exceptions import RemoteProtocolError, LocalProtocolError, map_exceptions from .._types import URL, Headers, TimeoutDict from .._utils import get_logger from .base import SyncByteStream, ConnectionState @@ -91,7 +91,8 @@ def _send_request( """ logger.trace("send_request method=%r url=%r headers=%s", method, url, headers) _scheme, _host, _port, target = url - event = h11.Request(method=method, target=target, headers=headers) + with map_exceptions({h11.LocalProtocolError: LocalProtocolError}): + event = h11.Request(method=method, target=target, headers=headers) self._send_event(event, timeout) def _send_request_body( @@ -151,7 +152,7 @@ def _receive_event(self, timeout: TimeoutDict) -> H11Event: Read a single `h11` event, reading more data from the network if needed. """ while True: - with map_exceptions({h11.RemoteProtocolError: ProtocolError}): + with map_exceptions({h11.RemoteProtocolError: RemoteProtocolError}): event = self.h11_state.next_event() if event is h11.NEED_DATA: diff --git a/httpcore/_sync/http2.py b/httpcore/_sync/http2.py index 2c420527..fba66858 100644 --- a/httpcore/_sync/http2.py +++ b/httpcore/_sync/http2.py @@ -9,7 +9,7 @@ from h2.settings import SettingCodes, Settings from .._backends.auto import SyncLock, SyncSemaphore, SyncSocketStream, SyncBackend -from .._exceptions import PoolTimeout, ProtocolError +from .._exceptions import PoolTimeout, RemoteProtocolError from .._types import URL, Headers, TimeoutDict from .._utils import get_logger from .base import SyncByteStream, ConnectionState, NewConnectionRequired @@ -215,7 +215,7 @@ def receive_events(self, timeout: TimeoutDict) -> None: logger.trace("receive_event stream_id=%r event=%s", event_stream_id, event) if hasattr(event, "error_code"): - raise ProtocolError(event) + raise RemoteProtocolError(event) if event_stream_id in self.events: self.events[event_stream_id].append(event)