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 typing import TYPE_CHECKING, Union
6from multidict import MultiMapping
8from .typedefs import StrOrURL
10try:
11 import ssl
13 SSLContext = ssl.SSLContext
14except ImportError: # pragma: no cover
15 ssl = SSLContext = None # type: ignore[assignment]
17if TYPE_CHECKING:
18 from .client_reqrep import ClientResponse, ConnectionKey, Fingerprint, RequestInfo
19 from .http_parser import RawResponseMessage
20else:
21 RequestInfo = ClientResponse = ConnectionKey = RawResponseMessage = None
23__all__ = (
24 "ClientError",
25 "ClientConnectionError",
26 "ClientConnectionResetError",
27 "ClientOSError",
28 "ClientConnectorError",
29 "ClientProxyConnectionError",
30 "ClientSSLError",
31 "ClientConnectorDNSError",
32 "ClientConnectorSSLError",
33 "ClientConnectorCertificateError",
34 "ConnectionTimeoutError",
35 "SocketTimeoutError",
36 "ServerConnectionError",
37 "ServerTimeoutError",
38 "ServerDisconnectedError",
39 "ServerFingerprintMismatch",
40 "ClientResponseError",
41 "ClientHttpProxyError",
42 "WSServerHandshakeError",
43 "ContentTypeError",
44 "ClientPayloadError",
45 "InvalidURL",
46 "InvalidUrlClientError",
47 "RedirectClientError",
48 "NonHttpUrlClientError",
49 "InvalidUrlRedirectClientError",
50 "NonHttpUrlRedirectClientError",
51 "WSMessageTypeError",
52)
55class ClientError(Exception):
56 """Base class for client connection errors."""
59class ClientResponseError(ClientError):
60 """Base class for exceptions that occur after getting a response.
62 request_info: An instance of RequestInfo.
63 history: A sequence of responses, if redirects occurred.
64 status: HTTP status code.
65 message: Error message.
66 headers: Response headers.
67 """
69 def __init__(
70 self,
71 request_info: RequestInfo,
72 history: tuple[ClientResponse, ...],
73 *,
74 status: int | None = None,
75 message: str = "",
76 headers: MultiMapping[str] | None = None,
77 ) -> None:
78 self.request_info = request_info
79 if status is not None:
80 self.status = status
81 else:
82 self.status = 0
83 self.message = message
84 self.headers = headers
85 self.history = history
86 self.args = (request_info, history)
88 def __str__(self) -> str:
89 return f"{self.status}, message={self.message!r}, url={str(self.request_info.real_url)!r}"
91 def __repr__(self) -> str:
92 args = f"{self.request_info!r}, {self.history!r}"
93 if self.status != 0:
94 args += f", status={self.status!r}"
95 if self.message != "":
96 args += f", message={self.message!r}"
97 if self.headers is not None:
98 args += f", headers={self.headers!r}"
99 return f"{type(self).__name__}({args})"
102class ContentTypeError(ClientResponseError):
103 """ContentType found is not valid."""
106class WSServerHandshakeError(ClientResponseError):
107 """websocket server handshake error."""
110class ClientHttpProxyError(ClientResponseError):
111 """HTTP proxy error.
113 Raised in :class:`aiohttp.connector.TCPConnector` if
114 proxy responds with status other than ``200 OK``
115 on ``CONNECT`` request.
116 """
119class TooManyRedirects(ClientResponseError):
120 """Client was redirected too many times."""
123class ClientConnectionError(ClientError):
124 """Base class for client socket errors."""
127class ClientConnectionResetError(ClientConnectionError, ConnectionResetError):
128 """ConnectionResetError"""
131class ClientOSError(ClientConnectionError, OSError):
132 """OSError error."""
135class ClientConnectorError(ClientOSError):
136 """Client connector error.
138 Raised in :class:`aiohttp.connector.TCPConnector` if
139 a connection can not be established.
140 """
142 def __init__(self, connection_key: ConnectionKey, os_error: OSError) -> None:
143 self._conn_key = connection_key
144 self._os_error = os_error
145 super().__init__(os_error.errno, os_error.strerror)
146 self.args = (connection_key, os_error)
148 @property
149 def os_error(self) -> OSError:
150 return self._os_error
152 @property
153 def host(self) -> str:
154 return self._conn_key.host
156 @property
157 def port(self) -> int | None:
158 return self._conn_key.port
160 @property
161 def ssl(self) -> Union[SSLContext, bool, "Fingerprint"]:
162 return self._conn_key.ssl
164 def __str__(self) -> str:
165 return "Cannot connect to host {0.host}:{0.port} ssl:{1} [{2}]".format(
166 self, "default" if self.ssl is True else self.ssl, self.strerror
167 )
169 # OSError.__reduce__ does too much black magick
170 __reduce__ = BaseException.__reduce__
173class ClientConnectorDNSError(ClientConnectorError):
174 """DNS resolution failed during client connection.
176 Raised in :class:`aiohttp.connector.TCPConnector` if
177 DNS resolution fails.
178 """
181class ClientProxyConnectionError(ClientConnectorError):
182 """Proxy connection error.
184 Raised in :class:`aiohttp.connector.TCPConnector` if
185 connection to proxy can not be established.
186 """
189class UnixClientConnectorError(ClientConnectorError):
190 """Unix connector error.
192 Raised in :py:class:`aiohttp.connector.UnixConnector`
193 if connection to unix socket can not be established.
194 """
196 def __init__(
197 self, path: str, connection_key: ConnectionKey, os_error: OSError
198 ) -> None:
199 self._path = path
200 super().__init__(connection_key, os_error)
202 @property
203 def path(self) -> str:
204 return self._path
206 def __str__(self) -> str:
207 return "Cannot connect to unix socket {0.path} ssl:{1} [{2}]".format(
208 self, "default" if self.ssl is True else self.ssl, self.strerror
209 )
212class ServerConnectionError(ClientConnectionError):
213 """Server connection errors."""
216class ServerDisconnectedError(ServerConnectionError):
217 """Server disconnected."""
219 def __init__(self, message: RawResponseMessage | str | None = None) -> None:
220 if message is None:
221 message = "Server disconnected"
223 self.args = (message,)
224 self.message = message
227class ServerTimeoutError(ServerConnectionError, asyncio.TimeoutError):
228 """Server timeout error."""
231class ConnectionTimeoutError(ServerTimeoutError):
232 """Connection timeout error."""
235class SocketTimeoutError(ServerTimeoutError):
236 """Socket timeout error."""
239class ServerFingerprintMismatch(ServerConnectionError):
240 """SSL certificate does not match expected fingerprint."""
242 def __init__(self, expected: bytes, got: bytes, host: str, port: int) -> None:
243 self.expected = expected
244 self.got = got
245 self.host = host
246 self.port = port
247 self.args = (expected, got, host, port)
249 def __repr__(self) -> str:
250 return f"<{self.__class__.__name__} expected={self.expected!r} got={self.got!r} host={self.host!r} port={self.port!r}>"
253class ClientPayloadError(ClientError):
254 """Response payload error."""
257class InvalidURL(ClientError, ValueError):
258 """Invalid URL.
260 URL used for fetching is malformed, e.g. it doesn't contains host
261 part.
262 """
264 # Derive from ValueError for backward compatibility
266 def __init__(self, url: StrOrURL, description: str | None = None) -> None:
267 # The type of url is not yarl.URL because the exception can be raised
268 # on URL(url) call
269 self._url = url
270 self._description = description
272 if description:
273 super().__init__(url, description)
274 else:
275 super().__init__(url)
277 @property
278 def url(self) -> StrOrURL:
279 return self._url
281 @property
282 def description(self) -> "str | None":
283 return self._description
285 def __repr__(self) -> str:
286 return f"<{self.__class__.__name__} {self}>"
288 def __str__(self) -> str:
289 if self._description:
290 return f"{self._url} - {self._description}"
291 return str(self._url)
294class InvalidUrlClientError(InvalidURL):
295 """Invalid URL client error."""
298class RedirectClientError(ClientError):
299 """Client redirect error."""
302class NonHttpUrlClientError(ClientError):
303 """Non http URL client error."""
306class InvalidUrlRedirectClientError(InvalidUrlClientError, RedirectClientError):
307 """Invalid URL redirect client error."""
310class NonHttpUrlRedirectClientError(NonHttpUrlClientError, RedirectClientError):
311 """Non http URL redirect client error."""
314class ClientSSLError(ClientConnectorError):
315 """Base error for ssl.*Errors."""
318if ssl is not None:
319 cert_errors = (ssl.CertificateError,)
320 cert_errors_bases = (
321 ClientSSLError,
322 ssl.CertificateError,
323 )
325 ssl_errors = (ssl.SSLError,)
326 ssl_error_bases = (ClientSSLError, ssl.SSLError)
327else: # pragma: no cover
328 cert_errors = tuple() # type: ignore[unreachable]
329 cert_errors_bases = (
330 ClientSSLError,
331 ValueError,
332 )
334 ssl_errors = tuple()
335 ssl_error_bases = (ClientSSLError,)
338class ClientConnectorSSLError(*ssl_error_bases): # type: ignore[misc]
339 """Response ssl error."""
342class ClientConnectorCertificateError(*cert_errors_bases): # type: ignore[misc]
343 """Response certificate error."""
345 _conn_key: ConnectionKey
347 def __init__(
348 # TODO: If we require ssl in future, this can become ssl.CertificateError
349 self,
350 connection_key: ConnectionKey,
351 certificate_error: Exception,
352 ) -> None:
353 if isinstance(certificate_error, cert_errors + (OSError,)):
354 # ssl.CertificateError has errno and strerror, so we should be fine
355 os_error = certificate_error
356 else:
357 os_error = OSError()
359 super().__init__(connection_key, os_error)
360 self._certificate_error = certificate_error
361 self.args = (connection_key, certificate_error)
363 @property
364 def certificate_error(self) -> Exception:
365 return self._certificate_error
367 @property
368 def host(self) -> str:
369 return self._conn_key.host
371 @property
372 def port(self) -> int | None:
373 return self._conn_key.port
375 @property
376 def ssl(self) -> bool:
377 return self._conn_key.is_ssl
379 def __str__(self) -> str:
380 return (
381 f"Cannot connect to host {self.host}:{self.port} ssl:{self.ssl} "
382 f"[{self.certificate_error.__class__.__name__}: "
383 f"{self.certificate_error.args}]"
384 )
387class WSMessageTypeError(TypeError):
388 """WebSocket message type is not valid."""