1from __future__ import absolute_import
2from .packages.six.moves.http_client import IncompleteRead as httplib_IncompleteRead
3
4# Base Exceptions
5
6
7class HTTPError(Exception):
8    "Base exception used by this module."
9    pass
10
11
12class HTTPWarning(Warning):
13    "Base warning used by this module."
14    pass
15
16
17class PoolError(HTTPError):
18    "Base exception for errors caused within a pool."
19
20    def __init__(self, pool, message):
21        self.pool = pool
22        HTTPError.__init__(self, "%s: %s" % (pool, message))
23
24    def __reduce__(self):
25        # For pickling purposes.
26        return self.__class__, (None, None)
27
28
29class RequestError(PoolError):
30    "Base exception for PoolErrors that have associated URLs."
31
32    def __init__(self, pool, url, message):
33        self.url = url
34        PoolError.__init__(self, pool, message)
35
36    def __reduce__(self):
37        # For pickling purposes.
38        return self.__class__, (None, self.url, None)
39
40
41class SSLError(HTTPError):
42    "Raised when SSL certificate fails in an HTTPS connection."
43    pass
44
45
46class ProxyError(HTTPError):
47    "Raised when the connection to a proxy fails."
48
49    def __init__(self, message, error, *args):
50        super(ProxyError, self).__init__(message, error, *args)
51        self.original_error = error
52
53
54class DecodeError(HTTPError):
55    "Raised when automatic decoding based on Content-Type fails."
56    pass
57
58
59class ProtocolError(HTTPError):
60    "Raised when something unexpected happens mid-request/response."
61    pass
62
63
64#: Renamed to ProtocolError but aliased for backwards compatibility.
65ConnectionError = ProtocolError
66
67
68# Leaf Exceptions
69
70
71class MaxRetryError(RequestError):
72    """Raised when the maximum number of retries is exceeded.
73
74    :param pool: The connection pool
75    :type pool: :class:`~urllib3.connectionpool.HTTPConnectionPool`
76    :param string url: The requested Url
77    :param exceptions.Exception reason: The underlying error
78
79    """
80
81    def __init__(self, pool, url, reason=None):
82        self.reason = reason
83
84        message = "Max retries exceeded with url: %s (Caused by %r)" % (url, reason)
85
86        RequestError.__init__(self, pool, url, message)
87
88
89class HostChangedError(RequestError):
90    "Raised when an existing pool gets a request for a foreign host."
91
92    def __init__(self, pool, url, retries=3):
93        message = "Tried to open a foreign host with url: %s" % url
94        RequestError.__init__(self, pool, url, message)
95        self.retries = retries
96
97
98class TimeoutStateError(HTTPError):
99    """ Raised when passing an invalid state to a timeout """
100
101    pass
102
103
104class TimeoutError(HTTPError):
105    """ Raised when a socket timeout error occurs.
106
107    Catching this error will catch both :exc:`ReadTimeoutErrors
108    <ReadTimeoutError>` and :exc:`ConnectTimeoutErrors <ConnectTimeoutError>`.
109    """
110
111    pass
112
113
114class ReadTimeoutError(TimeoutError, RequestError):
115    "Raised when a socket timeout occurs while receiving data from a server"
116    pass
117
118
119# This timeout error does not have a URL attached and needs to inherit from the
120# base HTTPError
121class ConnectTimeoutError(TimeoutError):
122    "Raised when a socket timeout occurs while connecting to a server"
123    pass
124
125
126class NewConnectionError(ConnectTimeoutError, PoolError):
127    "Raised when we fail to establish a new connection. Usually ECONNREFUSED."
128    pass
129
130
131class EmptyPoolError(PoolError):
132    "Raised when a pool runs out of connections and no more are allowed."
133    pass
134
135
136class ClosedPoolError(PoolError):
137    "Raised when a request enters a pool after the pool has been closed."
138    pass
139
140
141class LocationValueError(ValueError, HTTPError):
142    "Raised when there is something wrong with a given URL input."
143    pass
144
145
146class LocationParseError(LocationValueError):
147    "Raised when get_host or similar fails to parse the URL input."
148
149    def __init__(self, location):
150        message = "Failed to parse: %s" % location
151        HTTPError.__init__(self, message)
152
153        self.location = location
154
155
156class ResponseError(HTTPError):
157    "Used as a container for an error reason supplied in a MaxRetryError."
158    GENERIC_ERROR = "too many error responses"
159    SPECIFIC_ERROR = "too many {status_code} error responses"
160
161
162class SecurityWarning(HTTPWarning):
163    "Warned when performing security reducing actions"
164    pass
165
166
167class SubjectAltNameWarning(SecurityWarning):
168    "Warned when connecting to a host with a certificate missing a SAN."
169    pass
170
171
172class InsecureRequestWarning(SecurityWarning):
173    "Warned when making an unverified HTTPS request."
174    pass
175
176
177class SystemTimeWarning(SecurityWarning):
178    "Warned when system time is suspected to be wrong"
179    pass
180
181
182class InsecurePlatformWarning(SecurityWarning):
183    "Warned when certain SSL configuration is not available on a platform."
184    pass
185
186
187class SNIMissingWarning(HTTPWarning):
188    "Warned when making a HTTPS request without SNI available."
189    pass
190
191
192class DependencyWarning(HTTPWarning):
193    """
194    Warned when an attempt is made to import a module with missing optional
195    dependencies.
196    """
197
198    pass
199
200
201class InvalidProxyConfigurationWarning(HTTPWarning):
202    """
203    Warned when using an HTTPS proxy and an HTTPS URL. Currently
204    urllib3 doesn't support HTTPS proxies and the proxy will be
205    contacted via HTTP instead. This warning can be fixed by
206    changing your HTTPS proxy URL into an HTTP proxy URL.
207
208    If you encounter this warning read this:
209    https://github.com/urllib3/urllib3/issues/1850
210    """
211
212    pass
213
214
215class ResponseNotChunked(ProtocolError, ValueError):
216    "Response needs to be chunked in order to read it as chunks."
217    pass
218
219
220class BodyNotHttplibCompatible(HTTPError):
221    """
222    Body should be httplib.HTTPResponse like (have an fp attribute which
223    returns raw chunks) for read_chunked().
224    """
225
226    pass
227
228
229class IncompleteRead(HTTPError, httplib_IncompleteRead):
230    """
231    Response length doesn't match expected Content-Length
232
233    Subclass of http_client.IncompleteRead to allow int value
234    for `partial` to avoid creating large objects on streamed
235    reads.
236    """
237
238    def __init__(self, partial, expected):
239        super(IncompleteRead, self).__init__(partial, expected)
240
241    def __repr__(self):
242        return "IncompleteRead(%i bytes read, %i more expected)" % (
243            self.partial,
244            self.expected,
245        )
246
247
248class InvalidHeader(HTTPError):
249    "The header provided was somehow invalid."
250    pass
251
252
253class ProxySchemeUnknown(AssertionError, ValueError):
254    "ProxyManager does not support the supplied scheme"
255    # TODO(t-8ch): Stop inheriting from AssertionError in v2.0.
256
257    def __init__(self, scheme):
258        message = "Not supported proxy scheme %s" % scheme
259        super(ProxySchemeUnknown, self).__init__(message)
260
261
262class HeaderParsingError(HTTPError):
263    "Raised by assert_header_parsing, but we convert it to a log.warning statement."
264
265    def __init__(self, defects, unparsed_data):
266        message = "%s, unparsed data: %r" % (defects or "Unknown", unparsed_data)
267        super(HeaderParsingError, self).__init__(message)
268
269
270class UnrewindableBodyError(HTTPError):
271    "urllib3 encountered an error when trying to rewind a body"
272    pass
273