exceptions.py 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. from __future__ import absolute_import
  2. from .packages.six.moves.http_client import IncompleteRead as httplib_IncompleteRead
  3. # Base Exceptions
  4. class HTTPError(Exception):
  5. """Base exception used by this module."""
  6. pass
  7. class HTTPWarning(Warning):
  8. """Base warning used by this module."""
  9. pass
  10. class PoolError(HTTPError):
  11. """Base exception for errors caused within a pool."""
  12. def __init__(self, pool, message):
  13. self.pool = pool
  14. HTTPError.__init__(self, "%s: %s" % (pool, message))
  15. def __reduce__(self):
  16. # For pickling purposes.
  17. return self.__class__, (None, None)
  18. class RequestError(PoolError):
  19. """Base exception for PoolErrors that have associated URLs."""
  20. def __init__(self, pool, url, message):
  21. self.url = url
  22. PoolError.__init__(self, pool, message)
  23. def __reduce__(self):
  24. # For pickling purposes.
  25. return self.__class__, (None, self.url, None)
  26. class SSLError(HTTPError):
  27. """Raised when SSL certificate fails in an HTTPS connection."""
  28. pass
  29. class ProxyError(HTTPError):
  30. """Raised when the connection to a proxy fails."""
  31. def __init__(self, message, error, *args):
  32. super(ProxyError, self).__init__(message, error, *args)
  33. self.original_error = error
  34. class DecodeError(HTTPError):
  35. """Raised when automatic decoding based on Content-Type fails."""
  36. pass
  37. class ProtocolError(HTTPError):
  38. """Raised when something unexpected happens mid-request/response."""
  39. pass
  40. #: Renamed to ProtocolError but aliased for backwards compatibility.
  41. ConnectionError = ProtocolError
  42. # Leaf Exceptions
  43. class MaxRetryError(RequestError):
  44. """Raised when the maximum number of retries is exceeded.
  45. :param pool: The connection pool
  46. :type pool: :class:`~urllib3.connectionpool.HTTPConnectionPool`
  47. :param string url: The requested Url
  48. :param exceptions.Exception reason: The underlying error
  49. """
  50. def __init__(self, pool, url, reason=None):
  51. self.reason = reason
  52. message = "Max retries exceeded with url: %s (Caused by %r)" % (url, reason)
  53. RequestError.__init__(self, pool, url, message)
  54. class HostChangedError(RequestError):
  55. """Raised when an existing pool gets a request for a foreign host."""
  56. def __init__(self, pool, url, retries=3):
  57. message = "Tried to open a foreign host with url: %s" % url
  58. RequestError.__init__(self, pool, url, message)
  59. self.retries = retries
  60. class TimeoutStateError(HTTPError):
  61. """Raised when passing an invalid state to a timeout"""
  62. pass
  63. class TimeoutError(HTTPError):
  64. """Raised when a socket timeout error occurs.
  65. Catching this error will catch both :exc:`ReadTimeoutErrors
  66. <ReadTimeoutError>` and :exc:`ConnectTimeoutErrors <ConnectTimeoutError>`.
  67. """
  68. pass
  69. class ReadTimeoutError(TimeoutError, RequestError):
  70. """Raised when a socket timeout occurs while receiving data from a server"""
  71. pass
  72. # This timeout error does not have a URL attached and needs to inherit from the
  73. # base HTTPError
  74. class ConnectTimeoutError(TimeoutError):
  75. """Raised when a socket timeout occurs while connecting to a server"""
  76. pass
  77. class NewConnectionError(ConnectTimeoutError, PoolError):
  78. """Raised when we fail to establish a new connection. Usually ECONNREFUSED."""
  79. pass
  80. class EmptyPoolError(PoolError):
  81. """Raised when a pool runs out of connections and no more are allowed."""
  82. pass
  83. class ClosedPoolError(PoolError):
  84. """Raised when a request enters a pool after the pool has been closed."""
  85. pass
  86. class LocationValueError(ValueError, HTTPError):
  87. """Raised when there is something wrong with a given URL input."""
  88. pass
  89. class LocationParseError(LocationValueError):
  90. """Raised when get_host or similar fails to parse the URL input."""
  91. def __init__(self, location):
  92. message = "Failed to parse: %s" % location
  93. HTTPError.__init__(self, message)
  94. self.location = location
  95. class URLSchemeUnknown(LocationValueError):
  96. """Raised when a URL input has an unsupported scheme."""
  97. def __init__(self, scheme):
  98. message = "Not supported URL scheme %s" % scheme
  99. super(URLSchemeUnknown, self).__init__(message)
  100. self.scheme = scheme
  101. class ResponseError(HTTPError):
  102. """Used as a container for an error reason supplied in a MaxRetryError."""
  103. GENERIC_ERROR = "too many error responses"
  104. SPECIFIC_ERROR = "too many {status_code} error responses"
  105. class SecurityWarning(HTTPWarning):
  106. """Warned when performing security reducing actions"""
  107. pass
  108. class SubjectAltNameWarning(SecurityWarning):
  109. """Warned when connecting to a host with a certificate missing a SAN."""
  110. pass
  111. class InsecureRequestWarning(SecurityWarning):
  112. """Warned when making an unverified HTTPS request."""
  113. pass
  114. class SystemTimeWarning(SecurityWarning):
  115. """Warned when system time is suspected to be wrong"""
  116. pass
  117. class InsecurePlatformWarning(SecurityWarning):
  118. """Warned when certain TLS/SSL configuration is not available on a platform."""
  119. pass
  120. class SNIMissingWarning(HTTPWarning):
  121. """Warned when making a HTTPS request without SNI available."""
  122. pass
  123. class DependencyWarning(HTTPWarning):
  124. """
  125. Warned when an attempt is made to import a module with missing optional
  126. dependencies.
  127. """
  128. pass
  129. class ResponseNotChunked(ProtocolError, ValueError):
  130. """Response needs to be chunked in order to read it as chunks."""
  131. pass
  132. class BodyNotHttplibCompatible(HTTPError):
  133. """
  134. Body should be :class:`http.client.HTTPResponse` like
  135. (have an fp attribute which returns raw chunks) for read_chunked().
  136. """
  137. pass
  138. class IncompleteRead(HTTPError, httplib_IncompleteRead):
  139. """
  140. Response length doesn't match expected Content-Length
  141. Subclass of :class:`http.client.IncompleteRead` to allow int value
  142. for ``partial`` to avoid creating large objects on streamed reads.
  143. """
  144. def __init__(self, partial, expected):
  145. super(IncompleteRead, self).__init__(partial, expected)
  146. def __repr__(self):
  147. return "IncompleteRead(%i bytes read, %i more expected)" % (
  148. self.partial,
  149. self.expected,
  150. )
  151. class InvalidChunkLength(HTTPError, httplib_IncompleteRead):
  152. """Invalid chunk length in a chunked response."""
  153. def __init__(self, response, length):
  154. super(InvalidChunkLength, self).__init__(
  155. response.tell(), response.length_remaining
  156. )
  157. self.response = response
  158. self.length = length
  159. def __repr__(self):
  160. return "InvalidChunkLength(got length %r, %i bytes read)" % (
  161. self.length,
  162. self.partial,
  163. )
  164. class InvalidHeader(HTTPError):
  165. """The header provided was somehow invalid."""
  166. pass
  167. class ProxySchemeUnknown(AssertionError, URLSchemeUnknown):
  168. """ProxyManager does not support the supplied scheme"""
  169. # TODO(t-8ch): Stop inheriting from AssertionError in v2.0.
  170. def __init__(self, scheme):
  171. # 'localhost' is here because our URL parser parses
  172. # localhost:8080 -> scheme=localhost, remove if we fix this.
  173. if scheme == "localhost":
  174. scheme = None
  175. if scheme is None:
  176. message = "Proxy URL had no scheme, should start with http:// or https://"
  177. else:
  178. message = (
  179. "Proxy URL had unsupported scheme %s, should use http:// or https://"
  180. % scheme
  181. )
  182. super(ProxySchemeUnknown, self).__init__(message)
  183. class ProxySchemeUnsupported(ValueError):
  184. """Fetching HTTPS resources through HTTPS proxies is unsupported"""
  185. pass
  186. class HeaderParsingError(HTTPError):
  187. """Raised by assert_header_parsing, but we convert it to a log.warning statement."""
  188. def __init__(self, defects, unparsed_data):
  189. message = "%s, unparsed data: %r" % (defects or "Unknown", unparsed_data)
  190. super(HeaderParsingError, self).__init__(message)
  191. class UnrewindableBodyError(HTTPError):
  192. """urllib3 encountered an error when trying to rewind a body"""
  193. pass