Skip to content

Commit

Permalink
fix: No more BytesWarnings
Browse files Browse the repository at this point in the history
Fixes #1236.

This patch makes all header operations operate on `bytes` and converts all headers and values to bytes before operation. With a follow up patch to `hpack` it should also increase efficiency as currently, `hpack` casts everything to a `str` first before converting back to bytes: https://github.com/python-hyper/hpack/blob/02afcab28ca56eb5259904fd414baa89e9f50266/src/hpack/hpack.py#L150-L151
  • Loading branch information
BYK committed Nov 14, 2024
1 parent 2730c5b commit 605f0ea
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 175 deletions.
3 changes: 2 additions & 1 deletion src/h2/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
from .frame_buffer import FrameBuffer
from .settings import Settings, SettingCodes
from .stream import H2Stream, StreamClosedBy
from .utilities import SizeLimitDict, guard_increment_window
from .utilities import SizeLimitDict, guard_increment_window, utf8_encode_headers
from .windows import WindowManager


Expand Down Expand Up @@ -976,6 +976,7 @@ def push_stream(self, stream_id, promised_stream_id, request_headers):
)
self.streams[promised_stream_id] = new_stream

request_headers = utf8_encode_headers(request_headers)
frames = stream.push_stream_in_band(
promised_stream_id, request_headers, self.encoder
)
Expand Down
8 changes: 3 additions & 5 deletions src/h2/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -589,11 +589,9 @@ def __init__(self):
self.field_value = None

def __repr__(self):
return (
"<AlternativeServiceAvailable origin:%s, field_value:%s>" % (
self.origin.decode('utf-8', 'ignore'),
self.field_value.decode('utf-8', 'ignore'),
)
return "<AlternativeServiceAvailable origin:%s, field_value:%s>" % (
self.origin.decode("utf-8", "replace"),
self.field_value.decode("utf-8", "replace"),
)


Expand Down
23 changes: 15 additions & 8 deletions src/h2/stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,16 @@
ProtocolError, StreamClosedError, InvalidBodyLengthError, FlowControlError
)
from .utilities import (
guard_increment_window, is_informational_response, authority_from_headers,
validate_headers, validate_outbound_headers, normalize_outbound_headers,
HeaderValidationFlags, extract_method_header, normalize_inbound_headers
guard_increment_window,
is_informational_response,
authority_from_headers,
utf8_encode_headers,
validate_headers,
validate_outbound_headers,
normalize_outbound_headers,
HeaderValidationFlags,
extract_method_header,
normalize_inbound_headers,
)
from .windows import WindowManager

Expand Down Expand Up @@ -851,8 +858,9 @@ def send_headers(self, headers, encoder, end_stream=False):
# we need to scan the header block to see if this is an informational
# response.
input_ = StreamInputs.SEND_HEADERS
if ((not self.state_machine.client) and
is_informational_response(headers)):

headers = utf8_encode_headers(headers)
if (not self.state_machine.client) and is_informational_response(headers):
if end_stream:
raise ProtocolError(
"Cannot set END_STREAM on informational responses."
Expand Down Expand Up @@ -1242,6 +1250,7 @@ def _build_headers_frames(self,
"""
# We need to lowercase the header names, and to ensure that secure
# header fields are kept out of compression contexts.

if self.config.normalize_outbound_headers:
# also we may want to split outbound cookies to improve
# headers compression
Expand Down Expand Up @@ -1318,9 +1327,7 @@ def _initialize_content_length(self, headers):
try:
self._expected_content_length = int(v, 10)
except ValueError:
raise ProtocolError(
"Invalid content-length header: %s" % v
)
raise ProtocolError(f"Invalid content-length header: {repr(v)}")

return

Expand Down
Loading

0 comments on commit 605f0ea

Please sign in to comment.