exceptions.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. """
  2. h2/exceptions
  3. ~~~~~~~~~~~~~
  4. Exceptions for the HTTP/2 module.
  5. """
  6. from __future__ import annotations
  7. from .errors import ErrorCodes
  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 = 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. #: The error code corresponds to this kind of Protocol Error.
  23. error_code = 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 corresponds to this kind of Protocol Error.
  30. error_code = 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. class FlowControlError(ProtocolError):
  37. """
  38. An attempted action violates flow control constraints.
  39. """
  40. #: The error code corresponds to this kind of Protocol Error.
  41. error_code = ErrorCodes.FLOW_CONTROL_ERROR
  42. class StreamIDTooLowError(ProtocolError):
  43. """
  44. An attempt was made to open a stream that had an ID that is lower than the
  45. highest ID we have seen on this connection.
  46. """
  47. def __init__(self, stream_id: int, max_stream_id: int) -> None:
  48. #: The ID of the stream that we attempted to open.
  49. self.stream_id = stream_id
  50. #: The current highest-seen stream ID.
  51. self.max_stream_id = max_stream_id
  52. def __str__(self) -> str:
  53. return f"StreamIDTooLowError: {self.stream_id} is lower than {self.max_stream_id}"
  54. class NoAvailableStreamIDError(ProtocolError):
  55. """
  56. There are no available stream IDs left to the connection. All stream IDs
  57. have been exhausted.
  58. .. versionadded:: 2.0.0
  59. """
  60. class NoSuchStreamError(ProtocolError):
  61. """
  62. A stream-specific action referenced a stream that does not exist.
  63. .. versionchanged:: 2.0.0
  64. Became a subclass of :class:`ProtocolError
  65. <h2.exceptions.ProtocolError>`
  66. """
  67. def __init__(self, stream_id: int) -> None:
  68. #: The stream ID corresponds to the non-existent stream.
  69. self.stream_id = stream_id
  70. class StreamClosedError(NoSuchStreamError):
  71. """
  72. A more specific form of
  73. :class:`NoSuchStreamError <h2.exceptions.NoSuchStreamError>`. Indicates
  74. that the stream has since been closed, and that all state relating to that
  75. stream has been removed.
  76. """
  77. def __init__(self, stream_id: int) -> None:
  78. #: The stream ID corresponds to the nonexistent stream.
  79. self.stream_id = stream_id
  80. #: The relevant HTTP/2 error code.
  81. self.error_code = ErrorCodes.STREAM_CLOSED
  82. # Any events that internal code may need to fire. Not relevant to
  83. # external users that may receive a StreamClosedError.
  84. self._events = [] # type: ignore
  85. class InvalidSettingsValueError(ProtocolError, ValueError):
  86. """
  87. An attempt was made to set an invalid Settings value.
  88. .. versionadded:: 2.0.0
  89. """
  90. def __init__(self, msg: str, error_code: ErrorCodes) -> None:
  91. super().__init__(msg)
  92. self.error_code = error_code
  93. class InvalidBodyLengthError(ProtocolError):
  94. """
  95. The remote peer sent more or less data that the Content-Length header
  96. indicated.
  97. .. versionadded:: 2.0.0
  98. """
  99. def __init__(self, expected: int, actual: int) -> None:
  100. self.expected_length = expected
  101. self.actual_length = actual
  102. def __str__(self) -> str:
  103. return f"InvalidBodyLengthError: Expected {self.expected_length} bytes, received {self.actual_length}"
  104. class UnsupportedFrameError(ProtocolError):
  105. """
  106. The remote peer sent a frame that is unsupported in this context.
  107. .. versionadded:: 2.1.0
  108. .. versionchanged:: 4.0.0
  109. Removed deprecated KeyError parent class.
  110. """
  111. class RFC1122Error(H2Error):
  112. """
  113. Emitted when users attempt to do something that is literally allowed by the
  114. relevant RFC, but is sufficiently ill-defined that it's unwise to allow
  115. users to actually do it.
  116. While there is some disagreement about whether or not we should be liberal
  117. in what accept, it is a truth universally acknowledged that we should be
  118. conservative in what emit.
  119. .. versionadded:: 2.4.0
  120. """
  121. # shazow says I'm going to regret naming the exception this way. If that
  122. # turns out to be true, TELL HIM NOTHING.
  123. class DenialOfServiceError(ProtocolError):
  124. """
  125. Emitted when the remote peer exhibits a behaviour that is likely to be an
  126. attempt to perform a Denial of Service attack on the implementation. This
  127. is a form of ProtocolError that carries a different error code, and allows
  128. more easy detection of this kind of behaviour.
  129. .. versionadded:: 2.5.0
  130. """
  131. #: The error code corresponds to this kind of
  132. #: :class:`ProtocolError <h2.exceptions.ProtocolError>`
  133. error_code = ErrorCodes.ENHANCE_YOUR_CALM