Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
headers = [
(':method', 'POST'),
(':path', '/package.Service/Method'),
('te', 'trailers'),
('content-type', 'application/grpc'),
('grpc-timeout', 'invalid'),
]
methods = {'/package.Service/Method': object()}
await call_handler(methods, stream, headers)
assert stream.__events__ == [
SendHeaders(headers=[
(':status', '200'),
('grpc-status', '2'), # UNKNOWN
('grpc-message', 'Invalid grpc-timeout header'),
], end_stream=True),
Reset(ErrorCodes.NO_ERROR),
]
def test_connectionterminated_repr(self, additional_data, data_repr):
"""
ConnectionTerminated has a useful debug representation.
"""
e = h2.events.ConnectionTerminated()
e.error_code = h2.errors.ErrorCodes.INADEQUATE_SECURITY
e.last_stream_id = 33
e.additional_data = additional_data
assert repr(e) == (
"" % data_repr
)
def data_received(self, event):
""" Called when data is received on a stream.
If there is any open `ReceiveStream`, write the data to it.
"""
stream_id = event.stream_id
log.debug("data received on stream %s: %s...", stream_id, event.data[:100])
receive_stream = self.receive_streams.get(stream_id)
if receive_stream is None:
try:
self.conn.reset_stream(stream_id, error_code=ErrorCodes.PROTOCOL_ERROR)
except StreamClosedError:
pass
return
receive_stream.write(event.data)
self.conn.acknowledge_received_data(event.flow_controlled_length, stream_id)
class TooManyStreamsError(ProtocolError):
"""
An attempt was made to open a stream that would lead to too many concurrent
streams.
"""
pass
class FlowControlError(ProtocolError):
"""
An attempted action violates flow control constraints.
"""
#: The error code that corresponds to this kind of
#: :class:`ProtocolError `
error_code = h2.errors.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, max_stream_id):
#: 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):
return "StreamIDTooLowError: %d is lower than %d" % (
def _handle_connection_terminated(self, event, is_server):
self.log("HTTP/2 connection terminated by {}: error code: {}, last stream id: {}, additional data: {}".format(
"server" if is_server else "client",
event.error_code,
event.last_stream_id,
event.additional_data), "info")
if event.error_code != h2.errors.ErrorCodes.NO_ERROR:
# Something terrible has happened - kill everything!
self.connections[self.client_conn].close_connection(
error_code=event.error_code,
last_stream_id=event.last_stream_id,
additional_data=event.additional_data
)
self.client_conn.send(self.connections[self.client_conn].data_to_send())
self._kill_all_streams()
else:
"""
Do not immediately terminate the other connection.
Some streams might be still sending data to the client.
"""
return False
def response_received(self, event):
""" Called when a response is received on a stream.
If the headers contain an error, we should raise it here.
"""
super().response_received(event)
stream_id = event.stream_id
response_stream = self.receive_streams.get(stream_id)
if response_stream is None:
self.conn.reset_stream(stream_id, error_code=ErrorCodes.PROTOCOL_ERROR)
return
headers = response_stream.headers
if int(headers.get("grpc-status", 0)) > 0:
error = GrpcError.from_headers(headers)
response_stream.close(error)
def _error_code_from_int(code):
"""
Given an integer error code, returns either one of :class:`ErrorCodes
` or, if not present in the known set of codes,
returns the integer directly.
"""
try:
return ErrorCodes(code)
except ValueError:
return code
def _handle_stream_reset(self, eid, event, is_server, other_conn):
if eid in self.streams:
self.streams[eid].kill()
if event.error_code == h2.errors.ErrorCodes.CANCEL:
if is_server:
other_stream_id = self.streams[eid].client_stream_id
else:
other_stream_id = self.streams[eid].server_stream_id
if other_stream_id is not None:
self.connections[other_conn].safe_reset_stream(other_stream_id, event.error_code)
return True
#: `.
REFUSED_STREAM = ErrorCodes.REFUSED_STREAM
#: Stream cancelled.
#:
#: .. deprecated:: 2.5.0
#: Deprecated in favour of :class:`ErrorCodes.CANCEL
#: `.
CANCEL = ErrorCodes.CANCEL
#: Compression state not updated.
#:
#: .. deprecated:: 2.5.0
#: Deprecated in favour of :class:`ErrorCodes.COMPRESSION_ERROR
#: `.
COMPRESSION_ERROR = ErrorCodes.COMPRESSION_ERROR
#: TCP connection error for CONNECT method.
#:
#: .. deprecated:: 2.5.0
#: Deprecated in favour of :class:`ErrorCodes.CONNECT_ERROR
#: `.
CONNECT_ERROR = ErrorCodes.CONNECT_ERROR
#: Processing capacity exceeded.
#:
#: .. deprecated:: 2.5.0
#: Deprecated in favour of :class:`ErrorCodes.ENHANCE_YOUR_CALM
#: `.
ENHANCE_YOUR_CALM = ErrorCodes.ENHANCE_YOUR_CALM
#: Negotiated TLS parameters not acceptable.
Given an integer error code, returns either one of :class:`ErrorCodes
` or, if not present in the known set of codes,
returns the integer directly.
"""
try:
return ErrorCodes(code)
except ValueError:
return code
#: Graceful shutdown.
#:
#: .. deprecated:: 2.5.0
#: Deprecated in favour of :class:`ErrorCodes.NO_ERROR
#: `.
NO_ERROR = ErrorCodes.NO_ERROR
#: Protocol error detected.
#:
#: .. deprecated:: 2.5.0
#: Deprecated in favour of :class:`ErrorCodes.PROTOCOL_ERROR
#: `.
PROTOCOL_ERROR = ErrorCodes.PROTOCOL_ERROR
#: Implementation fault.
#:
#: .. deprecated:: 2.5.0
#: Deprecated in favour of :class:`ErrorCodes.INTERNAL_ERROR
#: `.
INTERNAL_ERROR = ErrorCodes.INTERNAL_ERROR
#: Flow-control limits exceeded.