Coverage for /pythoncovmergedfiles/medio/medio/src/aiohttp/aiohttp/client_exceptions.py: 59%
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
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 "UploadAbortedError",
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 args: tuple[RequestInfo, tuple[ClientResponse, ...]]
71 def __init__(
72 self,
73 request_info: RequestInfo,
74 history: tuple[ClientResponse, ...],
75 *,
76 status: int | None = None,
77 message: str = "",
78 headers: Mapping[str, str] | None = None,
79 ) -> None:
80 self.request_info = request_info
81 if status is not None:
82 self.status = status
83 else:
84 self.status = 0
85 self.message = message
86 self.headers = headers
87 self.history = history
88 self.args = (request_info, history)
90 def __str__(self) -> str:
91 return f"{self.status}, message={self.message!r}, url={str(self.request_info.real_url)!r}"
93 def __repr__(self) -> str:
94 args = f"{self.request_info!r}, {self.history!r}"
95 if self.status != 0:
96 args += f", status={self.status!r}"
97 if self.message != "":
98 args += f", message={self.message!r}"
99 if self.headers is not None:
100 args += f", headers={self.headers!r}"
101 return f"{type(self).__name__}({args})"
104class ContentTypeError(ClientResponseError):
105 """ContentType found is not valid."""
108class WSServerHandshakeError(ClientResponseError):
109 """websocket server handshake error."""
112class ClientHttpProxyError(ClientResponseError):
113 """HTTP proxy error.
115 Raised in :class:`aiohttp.connector.TCPConnector` if
116 proxy responds with status other than ``200 OK``
117 on ``CONNECT`` request.
118 """
121class TooManyRedirects(ClientResponseError):
122 """Client was redirected too many times."""
125class ClientConnectionError(ClientError):
126 """Base class for client socket errors."""
129class ClientConnectionResetError(ClientConnectionError, ConnectionResetError):
130 """ConnectionResetError"""
133class ClientOSError(ClientConnectionError, OSError):
134 """OSError error."""
137class ClientConnectorError(ClientOSError):
138 """Client connector error.
140 Raised in :class:`aiohttp.connector.TCPConnector` if
141 a connection can not be established.
142 """
144 args: tuple[ConnectionKey, OSError]
146 def __init__(self, connection_key: ConnectionKey, os_error: OSError) -> None:
147 self._conn_key = connection_key
148 self._os_error = os_error
149 super().__init__(os_error.errno, os_error.strerror)
150 self.args = (connection_key, os_error)
152 @property
153 def os_error(self) -> OSError:
154 return self._os_error
156 @property
157 def host(self) -> str:
158 return self._conn_key.host
160 @property
161 def port(self) -> int | None:
162 return self._conn_key.port
164 @property
165 def ssl(self) -> "SSLContext | bool | Fingerprint":
166 return self._conn_key.ssl
168 def __str__(self) -> str:
169 return "Cannot connect to host {0.host}:{0.port} ssl:{1} [{2}]".format(
170 self, "default" if self.ssl is True else self.ssl, self.strerror
171 )
173 # OSError.__reduce__ does too much black magick
174 __reduce__ = BaseException.__reduce__
177class ClientConnectorDNSError(ClientConnectorError):
178 """DNS resolution failed during client connection.
180 Raised in :class:`aiohttp.connector.TCPConnector` if
181 DNS resolution fails.
182 """
185class ClientProxyConnectionError(ClientConnectorError):
186 """Proxy connection error.
188 Raised in :class:`aiohttp.connector.TCPConnector` if
189 connection to proxy can not be established.
190 """
193class UnixClientConnectorError(ClientConnectorError):
194 """Unix connector error.
196 Raised in :py:class:`aiohttp.connector.UnixConnector`
197 if connection to unix socket can not be established.
198 """
200 def __init__(
201 self, path: str, connection_key: ConnectionKey, os_error: OSError
202 ) -> None:
203 self._path = path
204 super().__init__(connection_key, os_error)
206 @property
207 def path(self) -> str:
208 return self._path
210 def __str__(self) -> str:
211 return "Cannot connect to unix socket {0.path} ssl:{1} [{2}]".format(
212 self, "default" if self.ssl is True else self.ssl, self.strerror
213 )
216class ServerConnectionError(ClientConnectionError):
217 """Server connection errors."""
220class ServerDisconnectedError(ServerConnectionError):
221 """Server disconnected."""
223 args: tuple[RawResponseMessage | str]
225 def __init__(self, message: RawResponseMessage | str | None = None) -> None:
226 if message is None:
227 message = "Server disconnected"
229 self.args = (message,)
230 self.message = message
233class ServerTimeoutError(ServerConnectionError, asyncio.TimeoutError):
234 """Server timeout error."""
237class ConnectionTimeoutError(ServerTimeoutError):
238 """Connection timeout error."""
241class SocketTimeoutError(ServerTimeoutError):
242 """Socket timeout error."""
245class ServerFingerprintMismatch(ServerConnectionError):
246 """SSL certificate does not match expected fingerprint."""
248 args: tuple[bytes, bytes, str, int]
250 def __init__(self, expected: bytes, got: bytes, host: str, port: int) -> None:
251 self.expected = expected
252 self.got = got
253 self.host = host
254 self.port = port
255 self.args = (expected, got, host, port)
257 def __repr__(self) -> str:
258 return f"<{self.__class__.__name__} expected={self.expected!r} got={self.got!r} host={self.host!r} port={self.port!r}>"
261class ClientPayloadError(ClientError):
262 """Response payload error."""
265class UploadAbortedError(ClientError):
266 """The request body was never fully sent."""
269class InvalidURL(ClientError, ValueError):
270 """Invalid URL.
272 URL used for fetching is malformed, e.g. it doesn't contains host
273 part.
274 """
276 # Derive from ValueError for backward compatibility
278 args: tuple[StrOrURL] | tuple[StrOrURL, str]
280 def __init__(self, url: StrOrURL, description: str | None = None) -> None:
281 # The type of url is not yarl.URL because the exception can be raised
282 # on URL(url) call
283 self._url = url
284 self._description = description
286 if description:
287 super().__init__(url, description)
288 else:
289 super().__init__(url)
291 @property
292 def url(self) -> StrOrURL:
293 return self._url
295 @property
296 def description(self) -> "str | None":
297 return self._description
299 def __repr__(self) -> str:
300 return f"<{self.__class__.__name__} {self}>"
302 def __str__(self) -> str:
303 if self._description:
304 return f"{self._url} - {self._description}"
305 return str(self._url)
308class InvalidUrlClientError(InvalidURL):
309 """Invalid URL client error."""
312class RedirectClientError(ClientError):
313 """Client redirect error."""
316class NonHttpUrlClientError(ClientError):
317 """Non http URL client error."""
320class InvalidUrlRedirectClientError(InvalidUrlClientError, RedirectClientError):
321 """Invalid URL redirect client error."""
324class NonHttpUrlRedirectClientError(NonHttpUrlClientError, RedirectClientError):
325 """Non http URL redirect client error."""
328class ClientSSLError(ClientConnectorError):
329 """Base error for ssl.*Errors."""
332if ssl is not None:
333 cert_errors = (ssl.CertificateError,)
334 cert_errors_bases = (
335 ClientSSLError,
336 ssl.CertificateError,
337 )
339 ssl_errors = (ssl.SSLError,)
340 ssl_error_bases = (ClientSSLError, ssl.SSLError)
341else: # pragma: no cover
342 cert_errors = tuple() # type: ignore[unreachable]
343 cert_errors_bases = (
344 ClientSSLError,
345 ValueError,
346 )
348 ssl_errors = tuple()
349 ssl_error_bases = (ClientSSLError,)
352class ClientConnectorSSLError(*ssl_error_bases): # type: ignore[misc]
353 """Response ssl error."""
356class ClientConnectorCertificateError(*cert_errors_bases): # type: ignore[misc]
357 """Response certificate error."""
359 _conn_key: ConnectionKey
360 args: tuple[ConnectionKey, Exception]
362 def __init__(
363 # TODO: If we require ssl in future, this can become ssl.CertificateError
364 self,
365 connection_key: ConnectionKey,
366 certificate_error: Exception,
367 ) -> None:
368 if isinstance(certificate_error, cert_errors + (OSError,)):
369 # ssl.CertificateError has errno and strerror, so we should be fine
370 os_error = certificate_error
371 else:
372 os_error = OSError()
374 super().__init__(connection_key, os_error)
375 self._certificate_error = certificate_error
376 self.args = (connection_key, certificate_error)
378 @property
379 def certificate_error(self) -> Exception:
380 return self._certificate_error
382 @property
383 def host(self) -> str:
384 return self._conn_key.host
386 @property
387 def port(self) -> int | None:
388 return self._conn_key.port
390 def __str__(self) -> str:
391 return (
392 f"Cannot connect to host {self.host}:{self.port} "
393 f"ssl:{'default' if self.ssl is True else self.ssl} "
394 f"[{self.certificate_error.__class__.__name__}: "
395 f"{self.certificate_error.args}]"
396 )
399class WSMessageTypeError(TypeError):
400 """WebSocket message type is not valid."""