net: replace hand-rolled transport with HttpClient#98
Merged
Conversation
Swap the ~7,300-line hand-rolled Starling.Net stack (UDP DNS, raw Socket dialer, BouncyCastle TLS, HTTP/1.1 parser, HTTP/2 + HPACK, connection pool, body decoders) for System.Net.Http.HttpClient over a configured SocketsHttpHandler. This reverses the founding "no HttpClient, no SslStream" decision, approved by the user, and accepts the native TLS dependency. StarlingHttpClient stays the public facade, so consumers (fetch, XHR, iframe, engine fetchers) do not change. Browser policy stays above the transport: - AllowAutoRedirect=false — the engine follows redirects. - UseCookies=false — our CookieJar (PSL, prefixes) drives cookies. - SecureConnector does the TLS handshake in ConnectCallback, validates the chain against the bundled CCADB root store via a managed CertificateVerifier (X509Chain + CustomRootTrust, no OS store), captures the verified leaf per origin for the lock UI, and holds the dns/tcp/tls telemetry spans. - Response headers are copied via the NonValidated view so duplicate Set-Cookie survives for fetch getSetCookie()/getAllResponseHeaders(). Net.Net drops from ~7,315 to ~1,793 production lines. Drops the BouncyCastle.Cryptography dependency. Retires the internal-protocol tests (H1/H2/HPACK, DNS, TCP, pool) and adds managed cert-verify and header-fidelity tests. Docs updated: 00_INDEX locked decision, 03_NETWORKING banner, AGENTS interop carve-out.
Contributor
There was a problem hiding this comment.
Pull request overview
As provided in the diff/context, this pull request updates the Test262 conformance “ratchet floor” thresholds used by the Starling.Js.Test262.Tests suite. Note that this does not match the PR title/description (which describe a major Starling.Net transport rewrite), so the PR metadata likely needs correction or the full set of code changes needs to be included.
Changes:
- Raised the Test262 “built-ins” conformance floor to 95.9%.
- Raised the Test262 “intl402” conformance floor to 99.5% and updated the rationale comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
codymullins
force-pushed
the
feat/httpclient-transition
branch
from
July 7, 2026 18:21
89f7eec to
15df7ab
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Replaces the ~7,300-line hand-rolled
Starling.Netstack (UDP DNS, rawSocketdialer, BouncyCastle TLS, HTTP/1.1 parser, HTTP/2 + HPACK, connection pool, body decoders) withSystem.Net.Http.HttpClientover a configuredSocketsHttpHandler.This reverses the founding "no
HttpClient, noSslStream" decision (approved by the user) and accepts a native-TLS dependency under the BCL.StarlingHttpClientstays the public facade, so no consumer changed — fetch, XHR, iframe loads, and the engine fetchers all still callSendAsync(HttpRequest) -> Result<HttpResponse, NetworkError>.Starling.Netproduction code drops from ~7,315 → ~1,793 lines;BouncyCastle.Cryptographyis gone.Browser policy stays above the transport
AllowAutoRedirect=false— the engine's redirect loop (Engine.FetchHtmlAsync) still ownsresponse.url/ per-hop control.UseCookies=false— ourCookieJar(PSL,__Host-/__Secure-, Secure) drives cookies, notCookieContainer.AutomaticDecompression=Allreplaces the hand-rolled body decoders.SecureConnector(new) does the TLS handshake itself inConnectCallback(returns an authenticatedSslStream, allowed since .NET 7): validates the chain against the bundled CCADB root store via a rewritten managedCertificateVerifier(X509Chain+CustomRootTrust, OS store not consulted), captures the verified leaf per origin for the shell lock UI, and holds the dns/tcp/tls telemetry spans..NonValidatedview so duplicateSet-Cookieand raw values survive forgetSetCookie()/getAllResponseHeaders().Tradeoffs
ConnectCallback-derived rather than a true span tree; lost custom TLS/cipher pinning, CRLSet hook, and the custom UDP DNS resolver.Tests
wp:M3-06emacOS TLS 1.3 crash does not reproduce on the current SDK.CertificateVerifierTests(managed trust/host/untrusted-root) and a duplicate-Set-Cookiefidelity test.Known caveat (not a regression)
EngineLiveHttpsTestsfails its SSIM golden for example.com (0.9526 vs 0.99). This is a rendering-fidelity golden, not a fetch failure — body-content asserts pass, and networking can't alter pixels given identical HTML. Re-baselining is a separate rendering decision.Docs
Updated
browser-plan/00_INDEX.md(locked-decision row),browser-plan/03_NETWORKING.md(status banner + fixes), andAGENTS.md(interop-policy carve-out).