Thanks to visit codestin.com
Credit goes to github.com

Skip to content

test_http2_websocket error "Ordinary CONNECT MUST NOT include :scheme or :path" #370

Description

@Joanna-D

hi,when i build package with python3-h2-4.4.1, i meet the testcases error as follow

2026-08-13 02:04:56 _____________________________ test_http2_websocket _____________________________
2026-08-13 02:04:56 
2026-08-13 02:04:56     @pytest.mark.asyncio
2026-08-13 02:04:56     async def test_http2_websocket() -> None:
2026-08-13 02:04:56         event_loop: asyncio.AbstractEventLoop = asyncio.get_running_loop()
2026-08-13 02:04:56     
2026-08-13 02:04:56         server = TCPServer(
2026-08-13 02:04:56             ASGIWrapper(sanity_framework),
2026-08-13 02:04:56             event_loop,
2026-08-13 02:04:56             Config(),
2026-08-13 02:04:56             WorkerContext(None),
2026-08-13 02:04:56             {},
2026-08-13 02:04:56             MemoryReader(),  # type: ignore
2026-08-13 02:04:56             MemoryWriter(http2=True),  # type: ignore
2026-08-13 02:04:56         )
2026-08-13 02:04:56         task = event_loop.create_task(server.run())
2026-08-13 02:04:56         h2_client = h2.connection.H2Connection()
2026-08-13 02:04:56         h2_client.initiate_connection()
2026-08-13 02:04:56         await server.reader.send(h2_client.data_to_send())  # type: ignore
2026-08-13 02:04:56         stream_id = h2_client.get_next_available_stream_id()
2026-08-13 02:04:56 >       h2_client.send_headers(
2026-08-13 02:04:56             stream_id,
2026-08-13 02:04:56             [
2026-08-13 02:04:56                 (":method", "CONNECT"),
2026-08-13 02:04:56                 (":path", "/"),
2026-08-13 02:04:56                 (":authority", "hypercorn"),
2026-08-13 02:04:56                 (":scheme", "https"),
2026-08-13 02:04:56                 ("sec-websocket-version", "13"),
2026-08-13 02:04:56             ],
2026-08-13 02:04:56         )
2026-08-13 02:04:56 
2026-08-13 02:04:56 event_loop = <_UnixSelectorEventLoop running=False closed=False debug=False>
2026-08-13 02:04:56 h2_client  = <h2.connection.H2Connection object at 0x7ff63177c610>
2026-08-13 02:04:56 server     = <hypercorn.asyncio.tcp_server.TCPServer object at 0x7ff63177eb50>
2026-08-13 02:04:56 stream_id  = 1
2026-08-13 02:04:56 task       = <Task pending name='Task-93' coro=<TCPServer.run() running at /home/lkp/rpmbuild/BUILDROOT/python-hypercorn-0.18.0-1.o...usr/lib/python3.11/site-packages/hypercorn/asyncio/tcp_server.py:73> wait_for=<Future pending cb=[Task.task_wakeup()]>>
2026-08-13 02:04:56 
2026-08-13 02:04:56 tests/asyncio/test_sanity.py:202: 
2026-08-13 02:04:56 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
2026-08-13 02:04:56 /usr/lib/python3.11/site-packages/h2/connection.py:809: in send_headers
2026-08-13 02:04:56     frames.extend(stream.send_headers(
2026-08-13 02:04:56         end_stream = False
2026-08-13 02:04:56         frames     = []
2026-08-13 02:04:56         headers    = [(':method', 'CONNECT'), (':path', '/'), (':authority', 'hypercorn'), (':scheme', 'https'), ('sec-websocket-version', '13')]
2026-08-13 02:04:56         max_open_streams = 4294967297
2026-08-13 02:04:56         priority_depends_on = None
2026-08-13 02:04:56         priority_exclusive = None
2026-08-13 02:04:56         priority_weight = None
2026-08-13 02:04:56         self       = <h2.connection.H2Connection object at 0x7ff63177c610>
2026-08-13 02:04:56         stream     = <H2Stream id:1 state:<StreamState.OPEN: 3>>
2026-08-13 02:04:56         stream_id  = 1
2026-08-13 02:04:56         value      = 0
2026-08-13 02:04:56 /usr/lib/python3.11/site-packages/h2/stream.py:891: in send_headers
2026-08-13 02:04:56     frames = self._build_headers_frames(
2026-08-13 02:04:56         bytes_headers = [(b':method', b'CONNECT'), (b':path', b'/'), (b':authority', b'hypercorn'), (b':scheme', b'https'), (b'sec-websocket-version', b'13')]
2026-08-13 02:04:56         encoder    = <hpack.hpack.Encoder object at 0x7ff63177ce10>
2026-08-13 02:04:56         end_stream = False
2026-08-13 02:04:56         events     = [<h2.events._RequestSent object at 0x7ff6318b0790>]
2026-08-13 02:04:56         hdr_validation_flags = HeaderValidationFlags(is_client=True, is_trailer=False, is_response_header=False, is_push_promise=False)
2026-08-13 02:04:56         headers    = [(':method', 'CONNECT'), (':path', '/'), (':authority', 'hypercorn'), (':scheme', 'https'), ('sec-websocket-version', '13')]
2026-08-13 02:04:56         hf         = HeadersFrame(stream_id=1, flags=[]): exclusive=False, depends_on=0, stream_weight=0, data=None
2026-08-13 02:04:56         input_     = <StreamInputs.SEND_HEADERS: 0>
2026-08-13 02:04:56         self       = <H2Stream id:1 state:<StreamState.OPEN: 3>>
2026-08-13 02:04:56 /usr/lib/python3.11/site-packages/h2/stream.py:1309: in _build_headers_frames
2026-08-13 02:04:56     encoded_headers = encoder.encode(headers)
2026-08-13 02:04:56                       ^^^^^^^^^^^^^^^^^^^^^^^
2026-08-13 02:04:56         encoder    = <hpack.hpack.Encoder object at 0x7ff63177ce10>
2026-08-13 02:04:56         first_frame = HeadersFrame(stream_id=1, flags=[]): exclusive=False, depends_on=0, stream_weight=0, data=None
2026-08-13 02:04:56         hdr_validation_flags = HeaderValidationFlags(is_client=True, is_trailer=False, is_response_header=False, is_push_promise=False)
2026-08-13 02:04:56         headers    = <generator object _check_path_header.<locals>.inner at 0x7ff63179ece0>
2026-08-13 02:04:56         self       = <H2Stream id:1 state:<StreamState.OPEN: 3>>
2026-08-13 02:04:56         should_split_outbound_cookies = False
2026-08-13 02:04:56 /usr/lib/python3.11/site-packages/hpack/hpack.py:280: in encode
2026-08-13 02:04:56     for header in hpack_headers:
2026-08-13 02:04:56         header     = (b'sec-websocket-version', b'13')
2026-08-13 02:04:56         header_block = [b'B\x87\xbd\xabN\x9c\x17\xb7\xff', b'\x84', b'A\x87\x9f\xd5e\xb0\x87\xb2\xaf', b'\x87', b'@\x8fAH\xb7\x82\xc6\x83\x93\xa9R\xb7r\xd8\x83\x1e\xaf\x82\x0b?']
2026-08-13 02:04:56         headers    = <generator object _check_path_header.<locals>.inner at 0x7ff63179ece0>
2026-08-13 02:04:56         hpack_headers = <generator object _check_path_header.<locals>.inner at 0x7ff63179ece0>
2026-08-13 02:04:56         huffman    = True
2026-08-13 02:04:56         new_header = (b'sec-websocket-version', b'13')
2026-08-13 02:04:56         self       = <hpack.hpack.Encoder object at 0x7ff63177ce10>
2026-08-13 02:04:56         sensitive  = False
2026-08-13 02:04:56 /usr/lib/python3.11/site-packages/h2/utilities.py:506: in inner
2026-08-13 02:04:56     for header in headers:
2026-08-13 02:04:56         header     = (b'sec-websocket-version', b'13')
2026-08-13 02:04:56         headers    = <generator object _validate_host_authority_header at 0x7ff631784140>
2026-08-13 02:04:56 /usr/lib/python3.11/site-packages/h2/utilities.py:448: in _validate_host_authority_header
2026-08-13 02:04:56     for header in headers:
2026-08-13 02:04:56         authority_header_val = b'hypercorn'
2026-08-13 02:04:56         header     = (b'sec-websocket-version', b'13')
2026-08-13 02:04:56         headers    = <generator object _reject_pseudo_header_fields at 0x7ff631899250>
2026-08-13 02:04:56         host_header_val = None
2026-08-13 02:04:56 /usr/lib/python3.11/site-packages/h2/utilities.py:359: in _reject_pseudo_header_fields
2026-08-13 02:04:56     _check_pseudo_header_field_acceptability(
2026-08-13 02:04:56         hdr_validation_flags = HeaderValidationFlags(is_client=True, is_trailer=False, is_response_header=False, is_push_promise=False)
2026-08-13 02:04:56         header     = (b'sec-websocket-version', b'13')
2026-08-13 02:04:56         headers    = <generator object _reject_connection_header at 0x7ff6317c4220>
2026-08-13 02:04:56         method     = b'CONNECT'
2026-08-13 02:04:56         seen_pseudo_header_fields = {b':authority', b':method', b':path', b':scheme'}
2026-08-13 02:04:56         seen_regular_header = True
2026-08-13 02:04:56 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
2026-08-13 02:04:56 
2026-08-13 02:04:56 pseudo_headers = {b':authority', b':method', b':path', b':scheme'}
2026-08-13 02:04:56 method = b'CONNECT'
2026-08-13 02:04:56 hdr_validation_flags = HeaderValidationFlags(is_client=True, is_trailer=False, is_response_header=False, is_push_promise=False)
2026-08-13 02:04:56 
2026-08-13 02:04:56     def _check_pseudo_header_field_acceptability(  # noqa: C901
2026-08-13 02:04:56             pseudo_headers: set[bytes | str] | set[bytes] | set[str],
2026-08-13 02:04:56             method: bytes | None,
2026-08-13 02:04:56             hdr_validation_flags: HeaderValidationFlags,
2026-08-13 02:04:56     ) -> None:
2026-08-13 02:04:56         """
2026-08-13 02:04:56         Given the set of pseudo-headers present in a header block and the
2026-08-13 02:04:56         validation flags, confirms that RFC 7540 allows them.
2026-08-13 02:04:56         """
2026-08-13 02:04:56         # Pseudo-header fields MUST NOT appear in trailers - RFC 7540 § 8.1.2.1
2026-08-13 02:04:56         if hdr_validation_flags.is_trailer and pseudo_headers:
2026-08-13 02:04:56             msg = f"Received pseudo-header in trailer {pseudo_headers}"
2026-08-13 02:04:56             raise ProtocolError(msg)
2026-08-13 02:04:56     
2026-08-13 02:04:56         # If ':status' pseudo-header is not there in a response header, reject it.
2026-08-13 02:04:56         # Similarly, if ':path', ':method', or ':scheme' are not there in a request
2026-08-13 02:04:56         # header, reject it. Additionally, if a response contains any request-only
2026-08-13 02:04:56         # headers or vice-versa, reject it.
2026-08-13 02:04:56         # Relevant RFC section: RFC 7540 § 8.1.2.4
2026-08-13 02:04:56         # https://tools.ietf.org/html/rfc7540#section-8.1.2.4
2026-08-13 02:04:56         if hdr_validation_flags.is_response_header:
2026-08-13 02:04:56             _assert_header_in_set(b":status", pseudo_headers)
2026-08-13 02:04:56             invalid_response_headers = pseudo_headers & _REQUEST_ONLY_HEADERS
2026-08-13 02:04:56             if invalid_response_headers:
2026-08-13 02:04:56                 msg = f"Encountered request-only headers {invalid_response_headers}"
2026-08-13 02:04:56                 raise ProtocolError(msg)
2026-08-13 02:04:56         elif (not hdr_validation_flags.is_response_header and
2026-08-13 02:04:56               not hdr_validation_flags.is_trailer):
2026-08-13 02:04:56             # Request header block.
2026-08-13 02:04:56             _assert_header_in_set(b":method", pseudo_headers)
2026-08-13 02:04:56     
2026-08-13 02:04:56             is_connect = (method == b"CONNECT")
2026-08-13 02:04:56             is_extended_connect = is_connect and (b":protocol" in pseudo_headers)
2026-08-13 02:04:56     
2026-08-13 02:04:56             if is_connect and not is_extended_connect:
2026-08-13 02:04:56                 # Ordinary CONNECT (RFC 9113 s8.3):
2026-08-13 02:04:56                 # MUST NOT include :scheme or :path.
2026-08-13 02:04:56                 if b":scheme" in pseudo_headers or b":path" in pseudo_headers:
2026-08-13 02:04:56                     msg = "Ordinary CONNECT MUST NOT include :scheme or :path"
2026-08-13 02:04:56 >                   raise ProtocolError(msg)
2026-08-13 02:04:56 E                   h2.exceptions.ProtocolError: Ordinary CONNECT MUST NOT include :scheme or :path
2026-08-13 02:04:56 
2026-08-13 02:04:56 hdr_validation_flags = HeaderValidationFlags(is_client=True, is_trailer=False, is_response_header=False, is_push_promise=False)
2026-08-13 02:04:56 is_connect = True
2026-08-13 02:04:56 is_extended_connect = False
2026-08-13 02:04:56 method     = b'CONNECT'
2026-08-13 02:04:56 msg        = 'Ordinary CONNECT MUST NOT include :scheme or :path'
2026-08-13 02:04:56 pseudo_headers = {b':authority', b':method', b':path', b':scheme'}
2026-08-13 02:04:56 
2026-08-13 02:04:56 /usr/lib/python3.11/site-packages/h2/utilities.py:403: ProtocolError
2026-08-13 02:04:56 _____________________________ test_http2_websocket _____________________________
2026-08-13 02:04:56   + Exception Group Traceback (most recent call last):
2026-08-13 02:04:56   |   File "/usr/lib/python3.11/site-packages/trio/_core/_run.py", line 1125, in __aexit__
2026-08-13 02:04:56   |     raise combined_error_from_nursery
2026-08-13 02:04:56   | ExceptionGroup: Exceptions from Trio nursery (1 sub-exception)
2026-08-13 02:04:56   +-+---------------- 1 ----------------
2026-08-13 02:04:56     | Traceback (most recent call last):
2026-08-13 02:04:56     |   File "/usr/lib/python3.11/site-packages/pytest_trio/plugin.py", line 195, in _fixture_manager
2026-08-13 02:04:56     |     yield nursery_fixture
2026-08-13 02:04:56     |   File "/usr/lib/python3.11/site-packages/pytest_trio/plugin.py", line 250, in run
2026-08-13 02:04:56     |     await self._func(**resolved_kwargs)
2026-08-13 02:04:56     |   File "/home/lkp/rpmbuild/BUILD/hypercorn-0.18.0/tests/trio/test_sanity.py", line 174, in test_http2_websocket
2026-08-13 02:04:56     |     h2_client.send_headers(
2026-08-13 02:04:56     |   File "/usr/lib/python3.11/site-packages/h2/connection.py", line 809, in send_headers
2026-08-13 02:04:56     |     frames.extend(stream.send_headers(
2026-08-13 02:04:56     |                   ^^^^^^^^^^^^^^^^^^^^
2026-08-13 02:04:56     |   File "/usr/lib/python3.11/site-packages/h2/stream.py", line 891, in send_headers
2026-08-13 02:04:56     |     frames = self._build_headers_frames(
2026-08-13 02:04:56     |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^
2026-08-13 02:04:56     |   File "/usr/lib/python3.11/site-packages/h2/stream.py", line 1309, in _build_headers_frames
2026-08-13 02:04:56     |     encoded_headers = encoder.encode(headers)
2026-08-13 02:04:56     |                       ^^^^^^^^^^^^^^^^^^^^^^^
2026-08-13 02:04:56     |   File "/usr/lib/python3.11/site-packages/hpack/hpack.py", line 280, in encode
2026-08-13 02:04:56     |     for header in hpack_headers:
2026-08-13 02:04:56     |   File "/usr/lib/python3.11/site-packages/h2/utilities.py", line 506, in inner
2026-08-13 02:04:56     |     for header in headers:
2026-08-13 02:04:56     |   File "/usr/lib/python3.11/site-packages/h2/utilities.py", line 448, in _validate_host_authority_header
2026-08-13 02:04:56     |     for header in headers:
2026-08-13 02:04:56     |   File "/usr/lib/python3.11/site-packages/h2/utilities.py", line 359, in _reject_pseudo_header_fields
2026-08-13 02:04:56     |     _check_pseudo_header_field_acceptability(
2026-08-13 02:04:56     |   File "/usr/lib/python3.11/site-packages/h2/utilities.py", line 403, in _check_pseudo_header_field_acceptability
2026-08-13 02:04:56     |     raise ProtocolError(msg)
2026-08-13 02:04:56     | h2.exceptions.ProtocolError: Ordinary CONNECT MUST NOT include :scheme or :path
2026-08-13 02:04:56     +------------------------------------
2026-08-13 02:04:56 =========================== short test summary info ============================
2026-08-13 02:04:56 FAILED tests/asyncio/test_sanity.py::test_http2_websocket - h2.exceptions.Pro...
2026-08-13 02:04:56 FAILED tests/trio/test_sanity.py::test_http2_websocket - ProtocolError('Ordin...
2026-08-13 02:04:56 ======================== 2 failed, 194 passed in 7.82s =========================

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions