gh-204: Support proxy environment variables - #387
Conversation
zooba
left a comment
There was a problem hiding this comment.
Fantastic PR. Only one minor comment, but the more critical piece is that both the _msbuild.py definitions are going to require the new .cpp file or else it won't compile.
Once that change is added, I'll trigger CI.
|
|
||
|
|
||
| class _ProxySettings: | ||
| __slots__ = ("mode", "proxy_list", "powershell_proxy", "username", "password") |
There was a problem hiding this comment.
Drop this - we're never going to have enough instances to care.
|
Thanks for the review @zooba ! I’ll drop |
Summary
NO_PROXY,HTTP_PROXY, andHTTPS_PROXYin the BITS, WinHTTP, and PowerShell download paths.Context
Python Manager currently uses the user's Windows proxy configuration, but it does not consistently allow that configuration to be overridden with the commonly used proxy environment variables. This is particularly limiting in environments where applications use an explicit proxy without enabling a system-wide Windows proxy.
This implementation follows the backend-specific behavior described in the maintainer's design summary.
Closes #204.
Changes
Proxy resolution
Proxy settings are resolved once when a request is created:
NO_PROXYselects a direct connection;HTTP_PROXYandHTTPS_PROXYproduce a protocol-specific proxy list;HTTPS_PROXYtake precedence, followed by credentials fromHTTP_PROXY;Proxy values without a scheme are treated as HTTP proxy URLs. Paths and query components are removed before an endpoint is passed to the native APIs.
BITS
BITS now selects
BG_JOB_PROXY_USAGE_NO_PROXYfor direct mode andBG_JOB_PROXY_USAGE_OVERRIDEfor explicit proxy configuration. The generated proxy list follows the format documented forIBackgroundCopyJob::SetProxySettings. Explicit Basic credentials are supplied when present; otherwise, the existing Negotiate behavior is retained.WinHTTP
WinHTTP applies a named proxy with
WINHTTP_OPTION_PROXYwhen an override is configured. For direct mode, it explicitly appliesWINHTTP_ACCESS_TYPE_NO_PROXYto the request. This is intentional because the session is opened with the default Windows proxy configuration, so merely skipping proxy setup would not reliably disable an inherited static proxy. The access modes and request-level proxy option are documented inWINHTTP_PROXY_INFOand the WinHTTP option flags.PowerShell
The PowerShell fallback receives normalized proxy settings through process-local environment variables. It uses
-ProxyCredentialfor explicit credentials and-ProxyUseDefaultCredentialsotherwise; these options are kept mutually exclusive as required byInvoke-WebRequest.For direct mode, the child process installs an empty
WebProxy. A parameterlessWebProxyhas no address and bypasses every destination, allowingNO_PROXYto suppress an inherited Windows proxy without changing system settings.Tests
The local HTTP test server can now act as a simple proxy and issue a Basic
407 Proxy Authentication Requiredchallenge. Integration coverage verifies:NO_PROXYis set andHTTP_PROXYis intentionally unreachable.Validation
Performed on Windows with Python 3.14.6:
python -m pymsbuild -c _msbuild_test.py: PASSpython -m pytest tests/test_urlutils.py -k proxy -q: PASS (13 passed)CONNECTsmoke test through a separate local proxy process tohttps://www.python.org/: PASS for BITS, WinHTTP, and PowerShellpython -m pytest -q:399 passed, with one environment-specific failure intests/test_shellext.py::test_RegReadStr. The test assumesHKCU\Environment\PATHisREG_EXPAND_SZ; it isREG_SZon the test machine. The failing shell-extension path is unchanged by this pull request.git diff --check: PASSCompatibility and risk
The native entry points accept the proxy settings as an optional final argument, preserving existing callers. The automatic proxy paths are unchanged when the environment variables are absent.
As specified in the issue's accepted design, any non-empty
NO_PROXYvalue selects a fully direct connection; this change does not implement per-host bypass-list matching. The committed integration proxy keeps the automated suite self-contained and covers HTTP routing and authentication. A separate end-to-end smoke test verified an authenticated407 Basicchallenge, a realCONNECTtunnel, TLS negotiation, and data transfer through BITS, WinHTTP, and PowerShell. This smoke test remains manual because it uses an external HTTPS endpoint.