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