exceptions.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. # -*- coding: utf-8 -*-
  2. """
  3. h2/exceptions
  4. ~~~~~~~~~~~~~
  5. Exceptions for the HTTP/2 module.
  6. """
  7. import h2.errors
  8. class H2Error(Exception):
  9. """
  10. The base class for all exceptions for the HTTP/2 module.
  11. """
  12. class ProtocolError(H2Error):
  13. """
  14. An action was attempted in violation of the HTTP/2 protocol.
  15. """
  16. #: The error code corresponds to this kind of Protocol Error.
  17. error_code = h2.errors.ErrorCodes.PROTOCOL_ERROR
  18. class FrameTooLargeError(ProtocolError):
  19. """
  20. The frame that we tried to send or that we received was too large.
  21. """
  22. #: This error code that corresponds to this kind of Protocol Error.
  23. error_code = h2.errors.ErrorCodes.FRAME_SIZE_ERROR
  24. class FrameDataMissingError(ProtocolError):
  25. """
  26. The frame that we received is missing some data.
  27. .. versionadded:: 2.0.0
  28. """
  29. #: The error code that corresponds to this kind of Protocol Error
  30. error_code = h2.errors.ErrorCodes.FRAME_SIZE_ERROR
  31. class TooManyStreamsError(ProtocolError):
  32. """
  33. An attempt was made to open a stream that would lead to too many concurrent
  34. streams.
  35. """
  36. pass
  37. class FlowControlError(ProtocolError):
  38. """
  39. An attempted action violates flow control constraints.
  40. """
  41. #: The error code that corresponds to this kind of
  42. #: :class:`ProtocolError <h2.exceptions.ProtocolError>`
  43. error_code = h2.errors.ErrorCodes.FLOW_CONTROL_ERROR
  44. class StreamIDTooLowError(ProtocolError):
  45. """
  46. An attempt was made to open a stream that had an ID that is lower than the
  47. highest ID we have seen on this connection.
  48. """
  49. def __init__(self, stream_id, max_stream_id):
  50. #: The ID of the stream that we attempted to open.
  51. self.stream_id = stream_id
  52. #: The current highest-seen stream ID.
  53. self.max_stream_id = max_stream_id
  54. def __str__(self):
  55. return "StreamIDTooLowError: %d is lower than %d" % (
  56. self.stream_id, self.max_stream_id
  57. )
  58. class NoAvailableStreamIDError(ProtocolError):
  59. """
  60. There are no available stream IDs left to the connection. All stream IDs
  61. have been exhausted.
  62. .. versionadded:: 2.0.0
  63. """
  64. pass
  65. class NoSuchStreamError(ProtocolError):
  66. """
  67. A stream-specific action referenced a stream that does not exist.
  68. .. versionchanged:: 2.0.0
  69. Became a subclass of :class:`ProtocolError
  70. <h2.exceptions.ProtocolError>`
  71. """
  72. def __init__(self, stream_id):
  73. #: The stream ID that corresponds to the non-existent stream.
  74. self.stream_id = stream_id
  75. class StreamClosedError(NoSuchStreamError):
  76. """
  77. A more specific form of
  78. :class:`NoSuchStreamError <h2.exceptions.NoSuchStreamError>`. Indicates
  79. that the stream has since been closed, and that all state relating to that
  80. stream has been removed.
  81. """
  82. def __init__(self, stream_id):
  83. #: The stream ID that corresponds to the nonexistent stream.
  84. self.stream_id = stream_id
  85. #: The relevant HTTP/2 error code.
  86. self.error_code = h2.errors.ErrorCodes.STREAM_CLOSED
  87. # Any events that internal code may need to fire. Not relevant to
  88. # external users that may receive a StreamClosedError.
  89. self._events = []
  90. class InvalidSettingsValueError(ProtocolError, ValueError):
  91. """
  92. An attempt was made to set an invalid Settings value.
  93. .. versionadded:: 2.0.0
  94. """
  95. def __init__(self, msg, error_code):
  96. super(InvalidSettingsValueError, self).__init__(msg)
  97. self.error_code = error_code
  98. class InvalidBodyLengthError(ProtocolError):
  99. """
  100. The remote peer sent more or less data that the Content-Length header
  101. indicated.
  102. .. versionadded:: 2.0.0
  103. """
  104. def __init__(self, expected, actual):
  105. self.expected_length = expected
  106. self.actual_length = actual
  107. def __str__(self):
  108. return "InvalidBodyLengthError: Expected %d bytes, received %d" % (
  109. self.expected_length, self.actual_length
  110. )
  111. class UnsupportedFrameError(ProtocolError, KeyError):
  112. """
  113. The remote peer sent a frame that is unsupported in this context.
  114. .. versionadded:: 2.1.0
  115. """
  116. # TODO: Remove the KeyError in 3.0.0
  117. pass
  118. class RFC1122Error(H2Error):
  119. """
  120. Emitted when users attempt to do something that is literally allowed by the
  121. relevant RFC, but is sufficiently ill-defined that it's unwise to allow
  122. users to actually do it.
  123. While there is some disagreement about whether or not we should be liberal
  124. in what accept, it is a truth universally acknowledged that we should be
  125. conservative in what emit.
  126. .. versionadded:: 2.4.0
  127. """
  128. # shazow says I'm going to regret naming the exception this way. If that
  129. # turns out to be true, TELL HIM NOTHING.
  130. pass
  131. class DenialOfServiceError(ProtocolError):
  132. """
  133. Emitted when the remote peer exhibits a behaviour that is likely to be an
  134. attempt to perform a Denial of Service attack on the implementation. This
  135. is a form of ProtocolError that carries a different error code, and allows
  136. more easy detection of this kind of behaviour.
  137. .. versionadded:: 2.5.0
  138. """
  139. #: The error code that corresponds to this kind of
  140. #: :class:`ProtocolError <h2.exceptions.ProtocolError>`
  141. error_code = h2.errors.ErrorCodes.ENHANCE_YOUR_CALM