Skip to content

Conversation

chasingimpact
Copy link

@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.

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