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