Coverage for /pythoncovmergedfiles/medio/medio/src/aiohttp/aiohttp/client_exceptions.py: 58%
124 statements
« prev ^ index » next coverage.py v7.4.0, created at 2024-01-26 06:16 +0000
« prev ^ index » next coverage.py v7.4.0, created at 2024-01-26 06:16 +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:
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 "ConnectionTimeoutError",
32 "SocketTimeoutError",
33 "ServerConnectionError",
34 "ServerTimeoutError",
35 "ServerDisconnectedError",
36 "ServerFingerprintMismatch",
37 "ClientResponseError",
38 "ClientHttpProxyError",
39 "WSServerHandshakeError",
40 "ContentTypeError",
41 "ClientPayloadError",
42 "InvalidURL",
43)
46class ClientError(Exception):
47 """Base class for client connection errors."""
50class ClientResponseError(ClientError):
51 """Base class for exceptions that occur after getting a response.
53 request_info: An instance of RequestInfo.
54 history: A sequence of responses, if redirects occurred.
55 status: HTTP status code.
56 message: Error message.
57 headers: Response headers.
58 """
60 def __init__(
61 self,
62 request_info: RequestInfo,
63 history: Tuple[ClientResponse, ...],
64 *,
65 status: Optional[int] = None,
66 message: str = "",
67 headers: Optional[LooseHeaders] = None,
68 ) -> None:
69 self.request_info = request_info
70 if status is not None:
71 self.status = status
72 else:
73 self.status = 0
74 self.message = message
75 self.headers = headers
76 self.history = history
77 self.args = (request_info, history)
79 def __str__(self) -> str:
80 return "{}, message={!r}, url={!r}".format(
81 self.status,
82 self.message,
83 self.request_info.real_url,
84 )
86 def __repr__(self) -> str:
87 args = f"{self.request_info!r}, {self.history!r}"
88 if self.status != 0:
89 args += f", status={self.status!r}"
90 if self.message != "":
91 args += f", message={self.message!r}"
92 if self.headers is not None:
93 args += f", headers={self.headers!r}"
94 return f"{type(self).__name__}({args})"
97class ContentTypeError(ClientResponseError):
98 """ContentType found is not valid."""
101class WSServerHandshakeError(ClientResponseError):
102 """websocket server handshake error."""
105class ClientHttpProxyError(ClientResponseError):
106 """HTTP proxy error.
108 Raised in :class:`aiohttp.connector.TCPConnector` if
109 proxy responds with status other than ``200 OK``
110 on ``CONNECT`` request.
111 """
114class TooManyRedirects(ClientResponseError):
115 """Client was redirected too many times."""
118class ClientConnectionError(ClientError):
119 """Base class for client socket errors."""
122class ClientOSError(ClientConnectionError, OSError):
123 """OSError error."""
126class ClientConnectorError(ClientOSError):
127 """Client connector error.
129 Raised in :class:`aiohttp.connector.TCPConnector` if
130 a connection can not be established.
131 """
133 def __init__(self, connection_key: ConnectionKey, os_error: OSError) -> None:
134 self._conn_key = connection_key
135 self._os_error = os_error
136 super().__init__(os_error.errno, os_error.strerror)
137 self.args = (connection_key, os_error)
139 @property
140 def os_error(self) -> OSError:
141 return self._os_error
143 @property
144 def host(self) -> str:
145 return self._conn_key.host
147 @property
148 def port(self) -> Optional[int]:
149 return self._conn_key.port
151 @property
152 def ssl(self) -> Union[SSLContext, bool, "Fingerprint"]:
153 return self._conn_key.ssl
155 def __str__(self) -> str:
156 return "Cannot connect to host {0.host}:{0.port} ssl:{1} [{2}]".format(
157 self, "default" if self.ssl is True else self.ssl, self.strerror
158 )
160 # OSError.__reduce__ does too much black magick
161 __reduce__ = BaseException.__reduce__
164class ClientProxyConnectionError(ClientConnectorError):
165 """Proxy connection error.
167 Raised in :class:`aiohttp.connector.TCPConnector` if
168 connection to proxy can not be established.
169 """
172class UnixClientConnectorError(ClientConnectorError):
173 """Unix connector error.
175 Raised in :py:class:`aiohttp.connector.UnixConnector`
176 if connection to unix socket can not be established.
177 """
179 def __init__(
180 self, path: str, connection_key: ConnectionKey, os_error: OSError
181 ) -> None:
182 self._path = path
183 super().__init__(connection_key, os_error)
185 @property
186 def path(self) -> str:
187 return self._path
189 def __str__(self) -> str:
190 return "Cannot connect to unix socket {0.path} ssl:{1} [{2}]".format(
191 self, "default" if self.ssl is True else self.ssl, self.strerror
192 )
195class ServerConnectionError(ClientConnectionError):
196 """Server connection errors."""
199class ServerDisconnectedError(ServerConnectionError):
200 """Server disconnected."""
202 def __init__(self, message: Union[RawResponseMessage, str, None] = None) -> None:
203 if message is None:
204 message = "Server disconnected"
206 self.args = (message,)
207 self.message = message
210class ServerTimeoutError(ServerConnectionError, asyncio.TimeoutError):
211 """Server timeout error."""
214class ConnectionTimeoutError(ServerTimeoutError):
215 """Connection timeout error."""
218class SocketTimeoutError(ServerTimeoutError):
219 """Socket timeout error."""
222class ServerFingerprintMismatch(ServerConnectionError):
223 """SSL certificate does not match expected fingerprint."""
225 def __init__(self, expected: bytes, got: bytes, host: str, port: int) -> None:
226 self.expected = expected
227 self.got = got
228 self.host = host
229 self.port = port
230 self.args = (expected, got, host, port)
232 def __repr__(self) -> str:
233 return "<{} expected={!r} got={!r} host={!r} port={!r}>".format(
234 self.__class__.__name__, self.expected, self.got, self.host, self.port
235 )
238class ClientPayloadError(ClientError):
239 """Response payload error."""
242class InvalidURL(ClientError, ValueError):
243 """Invalid URL.
245 URL used for fetching is malformed, e.g. it doesn't contains host
246 part.
247 """
249 # Derive from ValueError for backward compatibility
251 def __init__(self, url: Any) -> None:
252 # The type of url is not yarl.URL because the exception can be raised
253 # on URL(url) call
254 super().__init__(url)
256 @property
257 def url(self) -> Any:
258 return self.args[0]
260 def __repr__(self) -> str:
261 return f"<{self.__class__.__name__} {self.url}>"
264class ClientSSLError(ClientConnectorError):
265 """Base error for ssl.*Errors."""
268if ssl is not None:
269 cert_errors = (ssl.CertificateError,)
270 cert_errors_bases = (
271 ClientSSLError,
272 ssl.CertificateError,
273 )
275 ssl_errors = (ssl.SSLError,)
276 ssl_error_bases = (ClientSSLError, ssl.SSLError)
277else: # pragma: no cover
278 cert_errors = tuple()
279 cert_errors_bases = (
280 ClientSSLError,
281 ValueError,
282 )
284 ssl_errors = tuple()
285 ssl_error_bases = (ClientSSLError,)
288class ClientConnectorSSLError(*ssl_error_bases): # type: ignore[misc]
289 """Response ssl error."""
292class ClientConnectorCertificateError(*cert_errors_bases): # type: ignore[misc]
293 """Response certificate error."""
295 def __init__(
296 self, connection_key: ConnectionKey, certificate_error: Exception
297 ) -> None:
298 self._conn_key = connection_key
299 self._certificate_error = certificate_error
300 self.args = (connection_key, certificate_error)
302 @property
303 def certificate_error(self) -> Exception:
304 return self._certificate_error
306 @property
307 def host(self) -> str:
308 return self._conn_key.host
310 @property
311 def port(self) -> Optional[int]:
312 return self._conn_key.port
314 @property
315 def ssl(self) -> bool:
316 return self._conn_key.is_ssl
318 def __str__(self) -> str:
319 return (
320 "Cannot connect to host {0.host}:{0.port} ssl:{0.ssl} "
321 "[{0.certificate_error.__class__.__name__}: "
322 "{0.certificate_error.args}]".format(self)
323 )