Coverage for /pythoncovmergedfiles/medio/medio/src/aiohttp/aiohttp/client_exceptions.py: 58%
120 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-07 06:52 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-07 06:52 +0000
1"""HTTP related errors."""
3import asyncio
4from typing import TYPE_CHECKING, Any, Optional, Tuple, Union
6from .http_parser import RawResponseMessage
7from .typedefs import LooseHeaders
9try:
10 import ssl
12 SSLContext = ssl.SSLContext
13except ImportError: # pragma: no cover
14 ssl = SSLContext = None # type: ignore[assignment]
17if TYPE_CHECKING: # pragma: no cover
18 from .client_reqrep import ClientResponse, ConnectionKey, Fingerprint, RequestInfo
19else:
20 RequestInfo = ClientResponse = ConnectionKey = None
22__all__ = (
23 "ClientError",
24 "ClientConnectionError",
25 "ClientOSError",
26 "ClientConnectorError",
27 "ClientProxyConnectionError",
28 "ClientSSLError",
29 "ClientConnectorSSLError",
30 "ClientConnectorCertificateError",
31 "ServerConnectionError",
32 "ServerTimeoutError",
33 "ServerDisconnectedError",
34 "ServerFingerprintMismatch",
35 "ClientResponseError",
36 "ClientHttpProxyError",
37 "WSServerHandshakeError",
38 "ContentTypeError",
39 "ClientPayloadError",
40 "InvalidURL",
41)
44class ClientError(Exception):
45 """Base class for client connection errors."""
48class ClientResponseError(ClientError):
49 """Base class for exceptions that occur after getting a response.
51 request_info: An instance of RequestInfo.
52 history: A sequence of responses, if redirects occurred.
53 status: HTTP status code.
54 message: Error message.
55 headers: Response headers.
56 """
58 def __init__(
59 self,
60 request_info: RequestInfo,
61 history: Tuple[ClientResponse, ...],
62 *,
63 status: Optional[int] = None,
64 message: str = "",
65 headers: Optional[LooseHeaders] = None,
66 ) -> None:
67 self.request_info = request_info
68 if status is not None:
69 self.status = status
70 else:
71 self.status = 0
72 self.message = message
73 self.headers = headers
74 self.history = history
75 self.args = (request_info, history)
77 def __str__(self) -> str:
78 return "{}, message={!r}, url={!r}".format(
79 self.status,
80 self.message,
81 self.request_info.real_url,
82 )
84 def __repr__(self) -> str:
85 args = f"{self.request_info!r}, {self.history!r}"
86 if self.status != 0:
87 args += f", status={self.status!r}"
88 if self.message != "":
89 args += f", message={self.message!r}"
90 if self.headers is not None:
91 args += f", headers={self.headers!r}"
92 return f"{type(self).__name__}({args})"
95class ContentTypeError(ClientResponseError):
96 """ContentType found is not valid."""
99class WSServerHandshakeError(ClientResponseError):
100 """websocket server handshake error."""
103class ClientHttpProxyError(ClientResponseError):
104 """HTTP proxy error.
106 Raised in :class:`aiohttp.connector.TCPConnector` if
107 proxy responds with status other than ``200 OK``
108 on ``CONNECT`` request.
109 """
112class TooManyRedirects(ClientResponseError):
113 """Client was redirected too many times."""
116class ClientConnectionError(ClientError):
117 """Base class for client socket errors."""
120class ClientOSError(ClientConnectionError, OSError):
121 """OSError error."""
124class ClientConnectorError(ClientOSError):
125 """Client connector error.
127 Raised in :class:`aiohttp.connector.TCPConnector` if
128 a connection can not be established.
129 """
131 def __init__(self, connection_key: ConnectionKey, os_error: OSError) -> None:
132 self._conn_key = connection_key
133 self._os_error = os_error
134 super().__init__(os_error.errno, os_error.strerror)
135 self.args = (connection_key, os_error)
137 @property
138 def os_error(self) -> OSError:
139 return self._os_error
141 @property
142 def host(self) -> str:
143 return self._conn_key.host
145 @property
146 def port(self) -> Optional[int]:
147 return self._conn_key.port
149 @property
150 def ssl(self) -> Union[SSLContext, None, bool, "Fingerprint"]:
151 return self._conn_key.ssl
153 def __str__(self) -> str:
154 return "Cannot connect to host {0.host}:{0.port} ssl:{1} [{2}]".format(
155 self, self.ssl if self.ssl is not None else "default", self.strerror
156 )
158 # OSError.__reduce__ does too much black magick
159 __reduce__ = BaseException.__reduce__
162class ClientProxyConnectionError(ClientConnectorError):
163 """Proxy connection error.
165 Raised in :class:`aiohttp.connector.TCPConnector` if
166 connection to proxy can not be established.
167 """
170class UnixClientConnectorError(ClientConnectorError):
171 """Unix connector error.
173 Raised in :py:class:`aiohttp.connector.UnixConnector`
174 if connection to unix socket can not be established.
175 """
177 def __init__(
178 self, path: str, connection_key: ConnectionKey, os_error: OSError
179 ) -> None:
180 self._path = path
181 super().__init__(connection_key, os_error)
183 @property
184 def path(self) -> str:
185 return self._path
187 def __str__(self) -> str:
188 return "Cannot connect to unix socket {0.path} ssl:{1} [{2}]".format(
189 self, self.ssl if self.ssl is not None else "default", self.strerror
190 )
193class ServerConnectionError(ClientConnectionError):
194 """Server connection errors."""
197class ServerDisconnectedError(ServerConnectionError):
198 """Server disconnected."""
200 def __init__(self, message: Union[RawResponseMessage, str, None] = None) -> None:
201 if message is None:
202 message = "Server disconnected"
204 self.args = (message,)
205 self.message = message
208class ServerTimeoutError(ServerConnectionError, asyncio.TimeoutError):
209 """Server timeout error."""
212class ServerFingerprintMismatch(ServerConnectionError):
213 """SSL certificate does not match expected fingerprint."""
215 def __init__(self, expected: bytes, got: bytes, host: str, port: int) -> None:
216 self.expected = expected
217 self.got = got
218 self.host = host
219 self.port = port
220 self.args = (expected, got, host, port)
222 def __repr__(self) -> str:
223 return "<{} expected={!r} got={!r} host={!r} port={!r}>".format(
224 self.__class__.__name__, self.expected, self.got, self.host, self.port
225 )
228class ClientPayloadError(ClientError):
229 """Response payload error."""
232class InvalidURL(ClientError, ValueError):
233 """Invalid URL.
235 URL used for fetching is malformed, e.g. it doesn't contains host
236 part.
237 """
239 # Derive from ValueError for backward compatibility
241 def __init__(self, url: Any) -> None:
242 # The type of url is not yarl.URL because the exception can be raised
243 # on URL(url) call
244 super().__init__(url)
246 @property
247 def url(self) -> Any:
248 return self.args[0]
250 def __repr__(self) -> str:
251 return f"<{self.__class__.__name__} {self.url}>"
254class ClientSSLError(ClientConnectorError):
255 """Base error for ssl.*Errors."""
258if ssl is not None:
259 cert_errors = (ssl.CertificateError,)
260 cert_errors_bases = (
261 ClientSSLError,
262 ssl.CertificateError,
263 )
265 ssl_errors = (ssl.SSLError,)
266 ssl_error_bases = (ClientSSLError, ssl.SSLError)
267else: # pragma: no cover
268 cert_errors = tuple()
269 cert_errors_bases = (
270 ClientSSLError,
271 ValueError,
272 )
274 ssl_errors = tuple()
275 ssl_error_bases = (ClientSSLError,)
278class ClientConnectorSSLError(*ssl_error_bases): # type: ignore[misc]
279 """Response ssl error."""
282class ClientConnectorCertificateError(*cert_errors_bases): # type: ignore[misc]
283 """Response certificate error."""
285 def __init__(
286 self, connection_key: ConnectionKey, certificate_error: Exception
287 ) -> None:
288 self._conn_key = connection_key
289 self._certificate_error = certificate_error
290 self.args = (connection_key, certificate_error)
292 @property
293 def certificate_error(self) -> Exception:
294 return self._certificate_error
296 @property
297 def host(self) -> str:
298 return self._conn_key.host
300 @property
301 def port(self) -> Optional[int]:
302 return self._conn_key.port
304 @property
305 def ssl(self) -> bool:
306 return self._conn_key.is_ssl
308 def __str__(self) -> str:
309 return (
310 "Cannot connect to host {0.host}:{0.port} ssl:{0.ssl} "
311 "[{0.certificate_error.__class__.__name__}: "
312 "{0.certificate_error.args}]".format(self)
313 )