Skip to content

Enable HTTP/2 and HTTP/3 across the NSURLSession, libcurl, and WinRT backends#35

Open
matthargett wants to merge 2 commits into
BabylonJS:mainfrom
rebeckerspecialties:http2-http3-enablement
Open

Enable HTTP/2 and HTTP/3 across the NSURLSession, libcurl, and WinRT backends#35
matthargett wants to merge 2 commits into
BabylonJS:mainfrom
rebeckerspecialties:http2-http3-enablement

Conversation

@matthargett

Copy link
Copy Markdown
Contributor

Opts every backend into the newest HTTP version its platform stack supports, negotiating downward automatically. Only https:// transfers are affected — http:// and file:// stay HTTP/1.1 — and every option falls back cleanly, so behavior against servers without h2/h3 is unchanged. Zero binary-size cost: no vendored network stacks; everything here is runtime detection or a request-level flag on the OS stack (a hard constraint for Babylon Native, which links UrlLib into shipped app binaries).

Per-platform support matrix

Platform Backend HTTP/2 HTTP/3 (QUIC) This PR
macOS / iOS NSURLSession automatic (ALPN) since macOS 10.11 / iOS 9 OS-supported; requires opt-in per request ✅ sets assumesHTTP3Capable on macOS 11.3+ / iOS 14.5+ (@available-guarded) — races QUIC vs TCP with fallback, so first requests can use h3 without prior Alt-Svc discovery
Linux libcurl ALPN h2 when built with nghttp2 (all mainstream distros) needs an h3-enabled curl build (Fedora ships one today; Ubuntu not yet) ✅ runtime curl_version_info detection: CURL_HTTP_VERSION_3 (with fallback, gated on curl ≥ 8.0 where VERSION_3 stopped meaning h3-or-fail) when CURL_VERSION_HTTP3 is present, else CURL_HTTP_VERSION_2TLS. The same binary lights up h3 as distros enable it
Windows Win32 + UWP Windows.Web.Http ALPN h2, Windows 10 1607+ OS has it (Windows 11 WinHTTP/msquic) but Windows.Web.Http exposes no knob — HttpVersion caps at Http20 ✅ pins HttpBaseProtocolFilter.MaxVersion = Http20 explicitly instead of trusting OS-build defaults; h3 documented as arriving with a WinHTTP-based backend (flag no-ops pre-Win11 and negotiates down, so Win10 1607 stays the supported floor)
Android java.net.HttpURLConnection ❌ platform stack is HTTP/1.1-only 📋 documented follow-up: embedded Cronet (h2 + h3 + Brotli). Devices without Google Play Services (Quest, Pico) need the embedded flavor; Quest 1 and Pico 4 both run Android 10 (API 29), clearing Cronet's Android 8 (API 26) minimum

Binary-size guidance for the two follow-ups (kept out of this PR deliberately)

  • Vendored curl on Linux (only needed if guaranteed-h3 matters before distros enable it): build with CMAKE_BUILD_TYPE=MinSizeRel + CMAKE_INTERPROCEDURAL_OPTIMIZATION=ON and HTTP_ONLY=ON (strips FTP/IMAP/SMTP/RTSP/etc.), no libpsl/brotli/zstd — an -Os/LTO curl+nghttp2 lands well under 1 MB; the QUIC TLS dependency is the real weight, which is why runtime detection is this PR's default.
  • Embedded Cronet on Android: ~4–8 MB per ABI even with LTO, and without GMS auto-update the app owns shipping network-stack security patches — both argue for keeping HttpURLConnection as a permanent runtime fallback rather than making Cronet load-bearing.

Verification

  • macOS: full suite green locally (8/8) with the h3 flag active on every network test; curl TU compiles clean under -Wall -Wextra.
  • Linux (gcc + clang) and Win32 (the HttpBaseProtocolFilter change): green on the fork CI runner — [CI runner] HTTP/2 + HTTP/3 enablement rebeckerspecialties/UrlLib#3.
  • The offline suite is unaffected by design (plain-http loopback and file:// never negotiate h2/h3), which is exactly the no-behavior-change property claimed above. Protocol observability (a NegotiatedProtocol() accessor feeding PerformanceResourceTiming.nextHopProtocol in JsRuntimeHost) is a named follow-up so this PR stays enablement-only.

…backends

- Apple: assumesHTTP3Capable on macOS 11.3+/iOS 14.5+ (races QUIC vs TCP
  with fallback; h2 already automatic via ALPN).
- Linux: runtime curl feature detection -- CURL_HTTP_VERSION_3 with
  fallback when curl >= 8.0 reports CURL_VERSION_HTTP3, else
  CURL_HTTP_VERSION_2TLS. Same binary lights up h3 as distros enable it;
  no vendoring, no size cost.
- Windows: pin HttpBaseProtocolFilter.MaxVersion = Http20 explicitly
  (Windows 10 1607+); Windows.Web.Http has no h3 knob -- documented as
  arriving with a WinHTTP-based backend.
- Readme: per-platform HTTP versions matrix incl. the Android/Cronet and
  WinHTTP follow-up plans.

Only https:// transfers are affected; http:// and file:// stay HTTP/1.1,
and every option negotiates downward, so behavior on servers without
h2/h3 is unchanged.
@matthargett

Copy link
Copy Markdown
Contributor Author

cc @bkaradzic-microsoft

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR updates UrlLib’s platform backends to prefer newer HTTP protocol versions (HTTP/2 where supported, and HTTP/3 where an OS stack exposes an opt-in), while documenting the behavior and preserving existing fallback behavior for servers/platforms that don’t support h2/h3.

Changes:

  • Windows (Windows.Web.Http): explicitly sets HttpBaseProtocolFilter.MaxVersion = Http20 to enable negotiated HTTP/2 via ALPN.
  • Linux (libcurl): adds runtime curl_version_info() feature detection to prefer HTTP/3 (with fallback) when available, otherwise HTTP/2-over-TLS.
  • Apple (NSURLSession): opts requests into HTTP/3 attempts via assumesHTTP3Capable behind an @available guard; README gains an HTTP versions matrix.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
Source/UrlRequest_Windows_Shared.h Enables HTTP/2 negotiation explicitly via HttpBaseProtocolFilter.MaxVersion.
Source/UrlRequest_Unix.cpp Adds runtime curl feature detection to select HTTP/3/HTTP/2 preferences.
Source/UrlRequest_Apple.mm Opts into HTTP/3 attempts on supported Apple OS versions via assumesHTTP3Capable.
README.md Documents per-platform HTTP/2/HTTP/3 behavior and backend constraints.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread Source/UrlRequest_Apple.mm Outdated
Comment thread Source/UrlRequest_Unix.cpp Outdated
Addresses review on BabylonJS#35:

- Apple: guard assumesHTTP3Capable with an SDK-version #if
  (__MAC_OS_X_VERSION_MAX_ALLOWED / __IPHONE_OS_VERSION_MAX_ALLOWED) so
  building against a pre-11.3/14.5 SDK compiles -- @available only gates
  the runtime deployment target, not SDK symbol availability. Restrict
  the opt-in to https:// (h3 is TLS-only).

- Unix: restrict CURLOPT_HTTP_VERSION to https:// scheme. Guard the h3
  and h2 blocks on LIBCURL_VERSION_NUM (a real curlver.h macro) instead
  of the CURL_HTTP_VERSION_* enum constants, which are invisible to the
  preprocessor -- '#if defined(CURL_HTTP_VERSION_3)' is always false. h3
  gated at >= 7.66.0, 2TLS at >= 7.47.0, so older system curl headers
  that lack the enums still build.

Verified: full suite green on macOS (8/8); Unix TU compiles -Wall -Wextra
against Homebrew curl 8.21 and Xcode SDK curl 8.7, and the guard pattern
compiles against fabricated 7.47 and 7.32 headers lacking the enums.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants