""" h2/exceptions ~~~~~~~~~~~~~ Exceptions for the HTTP/2 module. """ from __future__ import annotations from .errors import ErrorCodes class H2Error(Exception): """ The base class for all exceptions for the HTTP/2 module. """ class ProtocolError(H2Error): """ An action was attempted in violation of the HTTP/2 protocol. """ #: The error code corresponds to this kind of Protocol Error. error_code = ErrorCodes.PROTOCOL_ERROR class FrameTooLargeError(ProtocolError): """ The frame that we tried to send or that we received was too large. """ #: The error code corresponds to this kind of Protocol Error. error_code = ErrorCodes.FRAME_SIZE_ERROR class FrameDataMissingError(ProtocolError): """ The frame that we received is missing some data. .. versionadded:: 2.0.0 """ #: The error code corresponds to this kind of Protocol Error. error_code = ErrorCodes.FRAME_SIZE_ERROR class TooManyStreamsError(ProtocolError): """ An attempt was made to open a stream that would lead to too many concurrent streams. """ class FlowControlError(ProtocolError): """ An attempted action violates flow control constraints. """ #: The error code corresponds to this kind of Protocol Error. error_code = ErrorCodes.FLOW_CONTROL_ERROR class StreamIDTooLowError(ProtocolError): """ An attempt was made to open a stream that had an ID that is lower than the highest ID we have seen on this connection. """ def __init__(self, stream_id: int, max_stream_id: int) -> None: #: The ID of the stream that we attempted to open. self.stream_id = stream_id #: The current highest-seen stream ID. self.max_stream_id = max_stream_id def __str__(self) -> str: return f"StreamIDTooLowError: {self.stream_id} is lower than {self.max_stream_id}" class NoAvailableStreamIDError(ProtocolError): """ There are no available stream IDs left to the connection. All stream IDs have been exhausted. .. versionadded:: 2.0.0 """ class NoSuchStreamError(ProtocolError): """ A stream-specific action referenced a stream that does not exist. .. versionchanged:: 2.0.0 Became a subclass of :class:`ProtocolError ` """ def __init__(self, stream_id: int) -> None: #: The stream ID corresponds to the non-existent stream. self.stream_id = stream_id class StreamClosedError(NoSuchStreamError): """ A more specific form of :class:`NoSuchStreamError `. Indicates that the stream has since been closed, and that all state relating to that stream has been removed. """ def __init__(self, stream_id: int) -> None: #: The stream ID corresponds to the nonexistent stream. self.stream_id = stream_id #: The relevant HTTP/2 error code. self.error_code = ErrorCodes.STREAM_CLOSED # Any events that internal code may need to fire. Not relevant to # external users that may receive a StreamClosedError. self._events = [] # type: ignore class InvalidSettingsValueError(ProtocolError, ValueError): """ An attempt was made to set an invalid Settings value. .. versionadded:: 2.0.0 """ def __init__(self, msg: str, error_code: ErrorCodes) -> None: super().__init__(msg) self.error_code = error_code class InvalidBodyLengthError(ProtocolError): """ The remote peer sent more or less data that the Content-Length header indicated. .. versionadded:: 2.0.0 """ def __init__(self, expected: int, actual: int) -> None: self.expected_length = expected self.actual_length = actual def __str__(self) -> str: return f"InvalidBodyLengthError: Expected {self.expected_length} bytes, received {self.actual_length}" class UnsupportedFrameError(ProtocolError): """ The remote peer sent a frame that is unsupported in this context. .. versionadded:: 2.1.0 .. versionchanged:: 4.0.0 Removed deprecated KeyError parent class. """ class RFC1122Error(H2Error): """ Emitted when users attempt to do something that is literally allowed by the relevant RFC, but is sufficiently ill-defined that it's unwise to allow users to actually do it. While there is some disagreement about whether or not we should be liberal in what accept, it is a truth universally acknowledged that we should be conservative in what emit. .. versionadded:: 2.4.0 """ # shazow says I'm going to regret naming the exception this way. If that # turns out to be true, TELL HIM NOTHING. class DenialOfServiceError(ProtocolError): """ Emitted when the remote peer exhibits a behaviour that is likely to be an attempt to perform a Denial of Service attack on the implementation. This is a form of ProtocolError that carries a different error code, and allows more easy detection of this kind of behaviour. .. versionadded:: 2.5.0 """ #: The error code corresponds to this kind of #: :class:`ProtocolError ` error_code = ErrorCodes.ENHANCE_YOUR_CALM