Skip to content

Conversation

chasingimpact
Copy link
Contributor

@chasingimpact chasingimpact commented Oct 4, 2025

Summary

Aligns h2 with RFC 9113 s8.3 for ordinary CONNECT:

  • Ordinary CONNECT must include :method = CONNECT and :authority, and must not include :scheme or :path.
  • Extended CONNECT (f.e., RFC 8441 WebSocket) requires the regular tuple :scheme, :path, :authority plus :protocol.

fixes #1308
fixes #1247
fixes #319


Changes

Implementation details (utilities.py)

Changes are localized to header-validation helpers:

  • _check_pseudo_header_field_acceptability

    • Detects CONNECT mode:
      • Ordinary CONNECT: :method=CONNECT and no :protocol.
      • Extended CONNECT: :method=CONNECT and :protocol present.
    • Ordinary CONNECT branch:
      • Require: :method, :authority
      • Forbid: :scheme, :path (reject if present)
    • Extended CONNECT branch:
      • Require: :method, :authority, :scheme, :path, and :protocol
  • _reject_pseudo_header_fields

    • Delegates to the updated acceptability check above so ordinary CONNECT is not forced to have :path.
  • _validate_host_authority_header and validate_outbound_headers

    • No behavior changes beyond consuming the updated pseudo-header rules.
  • Inline comments added to document the split between ordinary vs. extended CONNECT and the relevant RFC sections.

Validation

  • Ordinary CONNECT: require :method and :authority; reject :scheme/:path if present.
  • Extended CONNECT (:protocol present): require :scheme, :path, :authority; keep existing checks.

Tests

tests/test_connect_pseudo_headers.py

  • Ordinary CONNECT without :path/:scheme -> accepted.
  • Extended CONNECT for WebSocket with full tuple -> accepted.

tests/test_connect_roundtrip_and_edges.py

  • Round-trip ordinary CONNECT (no :path) -> server receives RequestReceived.
  • Extended CONNECT round-trip.
  • Large header block (forces CONTINUATION).
  • Concurrent streams with ordinary CONNECT.

Rationale / Spec

  • RFC 9113 (HTTP/2) s8.3 -- CONNECT pseudo-header requirements for ordinary CONNECT.
  • RFC 8441 s4 -- Extended CONNECT for WebSocket; requires :scheme, :path, :authority, and :protocol.

Backward Compatibility

  • Ordinary CONNECT that previously errored now succeeds (spec-compliant).
  • Extended CONNECT behavior unchanged.
  • Non-CONNECT requests unchanged.

Testing

  • Local: full suite passed (1,612 tests).
  • New tests cover ordinary and extended CONNECT validation, round-trip, large header blocks, and concurrency.

Read more here: Parent issue

from h2.utilities import HeaderValidationFlags, validate_outbound_headers


Headers = Sequence[Tuple[str | bytes, str | bytes]]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this required here, or could it be re-used / imported from h2 itself? Otherwise I fear it might become outdated as both implementations diverge.

@Kriechi
Copy link
Member

Kriechi commented Oct 5, 2025

Thanks! This looks great overall. 🎉
One minor comment about the Header type.

Please un-do your changes to the .gitignore. I'm happy to add a few directories, but your removal of some lines will cause issues during the packaging/publishing process.

Please add a changelog entry.

@chasingimpact chasingimpact force-pushed the fix/ordinary-connect-no-path branch from 542f42c to 0d72e34 Compare October 7, 2025 20:23
@Kriechi
Copy link
Member

Kriechi commented Oct 8, 2025

Thanks - LGTM! 🎉

Only some code linting issues - which I need to find time to fix on the main branch, unless somebody beats me to it.

@Kriechi
Copy link
Member

Kriechi commented Oct 13, 2025

Master branch builds cleanly again - sorry for the newly introduced merge conflicts.

@Kriechi Kriechi merged commit 85068ed into python-hyper:master Oct 13, 2025
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants