[Foundation] Implement NSUrlSessionHandler proxy support. Fixes #14632 - #26021
[Foundation] Implement NSUrlSessionHandler proxy support. Fixes #14632#26021rolfbjarne wants to merge 19 commits into
Conversation
The Proxy setter previously threw PlatformNotSupportedException, and UseProxy/SupportsProxy didn't allow any custom proxy configuration. Implement custom proxy support: * Proxy is now a real IWebProxy property. Since NSUrlSession applies proxy settings per-session (not per-request), the proxy returned by IWebProxy.GetProxy for the first request is translated into the session's ConnectionProxyDictionary and the session is recreated before the first request is sent (mirroring the UseCookies pattern). * UseProxy is now a real settable bool. Setting it to false applies an empty connection proxy dictionary, which overrides any proxy configured in the OS. * SupportsProxy now returns true. * Proxy authentication is wired up: DefaultProxyCredentials is a real property, and proxy authentication challenges (IsProxy protection spaces) use Proxy.Credentials ?? DefaultProxyCredentials. Added an in-process HTTP forwarding proxy test server and tests covering proxy routing, proxy authentication (via Proxy.Credentials and DefaultProxyCredentials) and the proxy-related property behavior. Fixes #14632 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
…andling Proxy authentication challenges report a proxy authentication method (NSURLAuthenticationMethodHTTPProxy / NSURLAuthenticationMethodHTTPSProxy) rather than a specific scheme like Basic. TryGetAuthenticationType didn't recognize those methods and rejected the protection space, so the proxy credentials were never applied and requests failed with a 407. Handle proxy authentication challenges separately, using the proxy credentials (Proxy.Credentials or DefaultProxyCredentials) directly. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…support Implementing custom proxy support in NSUrlSessionHandler adds a small amount of reachable code, which increases the NativeAOT (TrimmableStatic) app size beyond the test tolerance on all platforms. Update the expected app size files accordingly. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
For a plain HTTP proxy using Basic authentication, NSUrlSession doesn't surface the proxy's 407 challenge to our session delegate, so the delegate-based credential flow never runs. Instead, embed the proxy credentials (kCFProxyUsernameKey/kCFProxyPasswordKey) directly in the connection proxy dictionary; NSUrlSession/CFNetwork then sends the Proxy-Authorization header automatically. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
…t diagnostics The kCFProxyUsernameKey/kCFProxyPasswordKey keys belong to the proxy entries returned by CFNetworkCopyProxiesForURL, not to the session's connectionProxyDictionary (which uses the kCFNetworkProxies* SystemConfiguration keys), so NSUrlSession ignored them. Revert that change. Add diagnostics (status code + proxy request counts) to the proxy authentication test assertion messages so the CI TestSummary reveals the actual runtime behavior (whether the proxy 407 triggers a delegate challenge/retry at all). Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
NSUrlSession only delivers a proxy authentication challenge to the delegate for CONNECT tunnels (HTTPS destinations); for a plain HTTP forward proxy it returns the 407 directly to the caller without a delegate challenge. So the proxy-auth tests must exercise an HTTPS destination through the proxy's CONNECT support. - Add CONNECT tunneling to ProxyTestServer (validate Proxy-Authorization, then 200 Connection Established + raw byte pipe to the target). - Extract the reusable in-proc TLS server (NWListener + self-signed cert) from MessageHandlers into a shared TlsTestServer helper. - Convert the two proxy-auth tests to GET an https:// TLS destination through the authenticating proxy. - Enable HTTPS proxying on non-macOS platforms via the literal "HTTPSEnable" key (the strongly-typed HttpsEnable property is macOS-only), required for CONNECT tunneling to work there. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
The CONNECT tunnel method was missing its closing brace, causing a CS1513 build failure in monotouch-test (and the autoformatter then over-indented the rest of the file). Restore the correct structure and indentation. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
CFNetwork bypasses the configured proxy for HTTPS (CONNECT) requests to localhost destinations, so the proxy never saw the request and AuthenticatedRequestCount stayed 0 on macOS and Mac Catalyst. Request a non-local hostname instead (so CFNetwork routes the CONNECT through the proxy) and have the test proxy tunnel every CONNECT to the local TLS test server via a new forceTunnelPort option. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Pull request overview
Implements end-to-end custom proxy support for NSUrlSessionHandler (previously throwing/limited), including proxy routing and proxy authentication, and adds in-process test infrastructure to validate behavior across Apple platforms.
Changes:
- Implement
Proxy,UseProxy,SupportsProxy, andDefaultProxyCredentialsinNSUrlSessionHandler, including per-session proxy configuration and proxy auth challenge handling. - Add in-process TLS server + HTTP forwarding proxy test server, and new tests validating proxy routing and authentication.
- Update app-size test baselines to account for the new code.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/monotouch-test/System.Net.Http/TlsTestServer.cs | Adds a reusable in-process TLS listener for HTTPS/proxy-tunneling tests. |
| tests/monotouch-test/System.Net.Http/ProxyTestServer.cs | Adds an in-process forwarding proxy with CONNECT support for proxy/auth tests. |
| tests/monotouch-test/System.Net.Http/NSUrlSessionHandlerTest.cs | Adds new tests for proxy routing, proxy auth, and property behavior. |
| tests/monotouch-test/System.Net.Http/MessageHandlers.cs | Refactors existing TLS listener helper usage to the new shared TlsTestServer. |
| tests/dotnet/UnitTests/expected/TVOS-NativeAOT-TrimmableStatic-size.txt | Updates size baseline after Foundation handler changes. |
| tests/dotnet/UnitTests/expected/MacOSX-NativeAOT-TrimmableStatic-size.txt | Updates size baseline after Foundation handler changes. |
| tests/dotnet/UnitTests/expected/MacCatalyst-NativeAOT-TrimmableStatic-size.txt | Updates size baseline after Foundation handler changes. |
| tests/dotnet/UnitTests/expected/iOS-NativeAOT-TrimmableStatic-size.txt | Updates size baseline after Foundation handler changes. |
| src/Foundation/NSUrlSessionHandler.cs | Implements proxy configuration/auth support and enables SupportsProxy. |
- NSUrlSessionHandler.SendAsync: mark the handler non-modifiable (set sentRequest) before configuring the session proxy, so handler properties can't be mutated once the first request has started. - ProxyTestServer.ReadBodyAsync: if the client disconnects early, return only the bytes actually read instead of a buffer padded with trailing zero bytes. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
|
/review |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
…net-implement-nsurlsessionhandler-membe-1e40bf
…downgrading
NSUrlSession's connection proxy dictionary can only describe a plain-HTTP
connection to the proxy: the HTTP/HTTPS proxy keys select which destination
scheme is proxied, not the protocol used to reach the proxy, and there's no
key to connect to the proxy over TLS or via SOCKS.
Previously the proxy uri's scheme was ignored (only host and port were used),
so a secure ('https') or SOCKS proxy would be silently connected to over plain
HTTP -- doing the wrong thing. Throw a NotSupportedException for any proxy
scheme other than 'http' so the misconfiguration fails loudly, and add a test.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
…net-implement-nsurlsessionhandler-membe-1e40bf
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
…net-implement-nsurlsessionhandler-membe-1e40bf # Conflicts: # tests/monotouch-test/System.Net.Http/MessageHandlers.cs
✅ API diff for current PR / commitNET (empty diffs)✅ API diff vs stableNET (empty diffs)ℹ️ Generator diffGenerator Diff: vsdrops (html) vsdrops (raw diff) gist (raw diff) - Please review changes) Pipeline on Agent |
🚀 [CI Build #6bffe0d] Test results 🚀Test results✅ All tests passed on VSTS: test results. 🎉 All 203 tests passed 🎉 Tests counts✅ assembly-processing: All 1 tests passed. Html Report (VSDrops) Download macOS tests✅ Tests on macOS Monterey (12): All 5 tests passed. Html Report (VSDrops) Download Linux Build VerificationPipeline on Agent |
The
Proxysetter previously threwPlatformNotSupportedException, andUseProxy/SupportsProxydidn't allow any custom proxy configuration.This implements custom proxy support:
Proxyis now a realIWebProxyproperty. Since NSUrlSession applies proxy settings per-session (not per-request), the proxy returned byIWebProxy.GetProxyfor the first request is translated into the session'sConnectionProxyDictionaryand the session is recreated before the first request is sent (mirroring theUseCookiespattern).UseProxyis now a real settable bool. Setting it tofalseapplies an empty connection proxy dictionary, which overrides any proxy configured in the OS.SupportsProxynow returnstrue.DefaultProxyCredentialsis a real property, and proxy authentication challenges (IsProxyprotection spaces) useProxy.Credentials ?? DefaultProxyCredentials.Added an in-process HTTP forwarding proxy test server and tests covering proxy routing, proxy authentication (via
Proxy.CredentialsandDefaultProxyCredentials) and the proxy-related property behavior.Fixes #14632.
Fixes #18635.
🤖 Pull request created by Copilot