Coverage for /pythoncovmergedfiles/medio/medio/src/aiohttp/aiohttp/client_exceptions.py: 57%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""HTTP related errors."""
3import asyncio
4from collections.abc import Mapping
5from typing import TYPE_CHECKING, Union
7from .typedefs import StrOrURL
9try:
10 import ssl
12 SSLContext = ssl.SSLContext
13except ImportError: # pragma: no cover
14 ssl = SSLContext = None # type: ignore[assignment]
16if TYPE_CHECKING:
17 from .client_reqrep import ClientResponse, ConnectionKey, Fingerprint, RequestInfo
18 from .http_parser import RawResponseMessage
19else:
20 RequestInfo = ClientResponse = ConnectionKey = RawResponseMessage = None
22__all__ = (
23 "ClientError",
24 "ClientConnectionError",
25 "ClientConnectionResetError",
26 "ClientOSError",
27 "ClientConnectorError",
28 "ClientProxyConnectionError",
29 "ClientSSLError",
30 "ClientConnectorDNSError",
31 "ClientConnectorSSLError",
32 "ClientConnectorCertificateError",
33 "ConnectionTimeoutError",
34 "SocketTimeoutError",
35 "ServerConnectionError",
36 "ServerTimeoutError",
37 "ServerDisconnectedError",
38 "ServerFingerprintMismatch",
39 "ClientResponseError",
40 "ClientHttpProxyError",
41 "WSServerHandshakeError",
42 "ContentTypeError",
43 "ClientPayloadError",
44 "InvalidURL",
45 "InvalidUrlClientError",
46 "RedirectClientError",
47 "NonHttpUrlClientError",
48 "InvalidUrlRedirectClientError",
49 "NonHttpUrlRedirectClientError",
50 "WSMessageTypeError",
51)
54class ClientError(Exception):
55 """Base class for client connection errors."""
58class ClientResponseError(ClientError):
59 """Base class for exceptions that occur after getting a response.
61 request_info: An instance of RequestInfo.
62 history: A sequence of responses, if redirects occurred.
63 status: HTTP status code.
64 message: Error message.
65 headers: Response headers.
66 """
68 def __init__(
69 self,
70 request_info: RequestInfo,
71 history: tuple[ClientResponse, ...],
72 *,
73 status: int | None = None,
74 message: str = "",
75 headers: Mapping[str, str] | None = None,
76 ) -> None:
77 self.request_info = request_info
78 if status is not None:
79 self.status = status
80 else:
81 self.status = 0
82 self.message = message
83 self.headers = headers
84 self.history = history
85 self.args = (request_info, history)
87 def __str__(self) -> str:
88 return f"{self.status}, message={self.message!r}, url={str(self.request_info.real_url)!r}"
90 def __repr__(self) -> str:
91 args = f"{self.request_info!r}, {self.history!r}"
92 if self.status != 0:
93 args += f", status={self.status!r}"
94 if self.message != "":
95 args += f", message={self.message!r}"
96 if self.headers is not None:
97 args += f", headers={self.headers!r}"
98 return f"{type(self).__name__}({args})"
101class ContentTypeError(ClientResponseError):
102 """ContentType found is not valid."""
105class WSServerHandshakeError(ClientResponseError):
106 """websocket server handshake error."""
109class ClientHttpProxyError(ClientResponseError):
110 """HTTP proxy error.
112 Raised in :class:`aiohttp.connector.TCPConnector` if
113 proxy responds with status other than ``200 OK``
114 on ``CONNECT`` request.
115 """
118class TooManyRedirects(ClientResponseError):
119 """Client was redirected too many times."""
122class ClientConnectionError(ClientError):
123 """Base class for client socket errors."""
126class ClientConnectionResetError(ClientConnectionError, ConnectionResetError):
127 """ConnectionResetError"""
130class ClientOSError(ClientConnectionError, OSError):
131 """OSError error."""
134class ClientConnectorError(ClientOSError):
135 """Client connector error.
137 Raised in :class:`aiohttp.connector.TCPConnector` if
138 a connection can not be established.
139 """
141 def __init__(self, connection_key: ConnectionKey, os_error: OSError) -> None:
142 self._conn_key = connection_key
143 self._os_error = os_error
144 super().__init__(os_error.errno, os_error.strerror)
145 self.args = (connection_key, os_error)
147 @property
148 def os_error(self) -> OSError:
149 return self._os_error
151 @property
152 def host(self) -> str:
153 return self._conn_key.host
155 @property
156 def port(self) -> int | None:
157 return self._conn_key.port
159 @property
160 def ssl(self) -> Union[SSLContext, bool, "Fingerprint"]:
161 return self._conn_key.ssl
163 def __str__(self) -> str:
164 return "Cannot connect to host {0.host}:{0.port} ssl:{1} [{2}]".format(
165 self, "default" if self.ssl is True else self.ssl, self.strerror
166 )
168 # OSError.__reduce__ does too much black magick
169 __reduce__ = BaseException.__reduce__
172class ClientConnectorDNSError(ClientConnectorError):
173 """DNS resolution failed during client connection.
175 Raised in :class:`aiohttp.connector.TCPConnector` if
176 DNS resolution fails.
177 """
180class ClientProxyConnectionError(ClientConnectorError):
181 """Proxy connection error.
183 Raised in :class:`aiohttp.connector.TCPConnector` if
184 connection to proxy can not be established.
185 """
188class UnixClientConnectorError(ClientConnectorError):
189 """Unix connector error.
191 Raised in :py:class:`aiohttp.connector.UnixConnector`
192 if connection to unix socket can not be established.
193 """
195 def __init__(
196 self, path: str, connection_key: ConnectionKey, os_error: OSError
197 ) -> None:
198 self._path = path
199 super().__init__(connection_key, os_error)
201 @property
202 def path(self) -> str:
203 return self._path
205 def __str__(self) -> str:
206 return "Cannot connect to unix socket {0.path} ssl:{1} [{2}]".format(
207 self, "default" if self.ssl is True else self.ssl, self.strerror
208 )
211class ServerConnectionError(ClientConnectionError):
212 """Server connection errors."""
215class ServerDisconnectedError(ServerConnectionError):
216 """Server disconnected."""
218 def __init__(self, message: RawResponseMessage | str | None = None) -> None:
219 if message is None:
220 message = "Server disconnected"
222 self.args = (message,)
223 self.message = message
226class ServerTimeoutError(ServerConnectionError, asyncio.TimeoutError):
227 """Server timeout error."""
230class ConnectionTimeoutError(ServerTimeoutError):
231 """Connection timeout error."""
234class SocketTimeoutError(ServerTimeoutError):
235 """Socket timeout error."""
238class ServerFingerprintMismatch(ServerConnectionError):
239 """SSL certificate does not match expected fingerprint."""
241 def __init__(self, expected: bytes, got: bytes, host: str, port: int) -> None:
242 self.expected = expected
243 self.got = got
244 self.host = host
245 self.port = port
246 self.args = (expected, got, host, port)
248 def __repr__(self) -> str:
249 return f"<{self.__class__.__name__} expected={self.expected!r} got={self.got!r} host={self.host!r} port={self.port!r}>"
252class ClientPayloadError(ClientError):
253 """Response payload error."""
256class InvalidURL(ClientError, ValueError):
257 """Invalid URL.
259 URL used for fetching is malformed, e.g. it doesn't contains host
260 part.
261 """
263 # Derive from ValueError for backward compatibility
265 def __init__(self, url: StrOrURL, description: str | None = None) -> None:
266 # The type of url is not yarl.URL because the exception can be raised
267 # on URL(url) call
268 self._url = url
269 self._description = description
271 if description:
272 super().__init__(url, description)
273 else:
274 super().__init__(url)
276 @property
277 def url(self) -> StrOrURL:
278 return self._url
280 @property
281 def description(self) -> "str | None":
282 return self._description
284 def __repr__(self) -> str:
285 return f"<{self.__class__.__name__} {self}>"
287 def __str__(self) -> str:
288 if self._description:
289 return f"{self._url} - {self._description}"
290 return str(self._url)
293class InvalidUrlClientError(InvalidURL):
294 """Invalid URL client error."""
297class RedirectClientError(ClientError):
298 """Client redirect error."""
301class NonHttpUrlClientError(ClientError):
302 """Non http URL client error."""
305class InvalidUrlRedirectClientError(InvalidUrlClientError, RedirectClientError):
306 """Invalid URL redirect client error."""
309class NonHttpUrlRedirectClientError(NonHttpUrlClientError, RedirectClientError):
310 """Non http URL redirect client error."""
313class ClientSSLError(ClientConnectorError):
314 """Base error for ssl.*Errors."""
317if ssl is not None:
318 cert_errors = (ssl.CertificateError,)
319 cert_errors_bases = (
320 ClientSSLError,
321 ssl.CertificateError,
322 )
324 ssl_errors = (ssl.SSLError,)
325 ssl_error_bases = (ClientSSLError, ssl.SSLError)
326else: # pragma: no cover
327 cert_errors = tuple() # type: ignore[unreachable]
328 cert_errors_bases = (
329 ClientSSLError,
330 ValueError,
331 )
333 ssl_errors = tuple()
334 ssl_error_bases = (ClientSSLError,)
337class ClientConnectorSSLError(*ssl_error_bases): # type: ignore[misc]
338 """Response ssl error."""
341class ClientConnectorCertificateError(*cert_errors_bases): # type: ignore[misc]
342 """Response certificate error."""
344 _conn_key: ConnectionKey
346 def __init__(
347 # TODO: If we require ssl in future, this can become ssl.CertificateError
348 self,
349 connection_key: ConnectionKey,
350 certificate_error: Exception,
351 ) -> None:
352 if isinstance(certificate_error, cert_errors + (OSError,)):
353 # ssl.CertificateError has errno and strerror, so we should be fine
354 os_error = certificate_error
355 else:
356 os_error = OSError()
358 super().__init__(connection_key, os_error)
359 self._certificate_error = certificate_error
360 self.args = (connection_key, certificate_error)
362 @property
363 def certificate_error(self) -> Exception:
364 return self._certificate_error
366 @property
367 def host(self) -> str:
368 return self._conn_key.host
370 @property
371 def port(self) -> int | None:
372 return self._conn_key.port
374 @property
375 def ssl(self) -> bool:
376 return self._conn_key.is_ssl
378 def __str__(self) -> str:
379 return (
380 f"Cannot connect to host {self.host}:{self.port} ssl:{self.ssl} "
381 f"[{self.certificate_error.__class__.__name__}: "
382 f"{self.certificate_error.args}]"
383 )
386class WSMessageTypeError(TypeError):
387 """WebSocket message type is not valid."""