Fix https proxy not set when pac is used (#40950)
Set https_proxy to http_proxy when PAC is used.
Feng Wang committed
Jul 3, 2026 at 10:19 UTC
533014f9a5f4644b0765693f5a501a36b1ceab73
2 files changed
+55
-5
src/windows/service/exe/LxssUserSession.cpp
+8
@@ -4102,6 +4102,14 @@ try
4102
// We only add uppercase as there is no standard environment variable for PAC proxies.
4103
// This at least makes the PAC url available to the user in case they wish to use it.
4104
environment.emplace_back(std::format("{}={}", c_pacProxy, proxySettings.PacUrl));
4105
+
4106
+ // When PAC is used, the reply only populates the proxy field.
4107
+ // Set both envs to this value as best effort since PAC is not functional in headless Linux.
4108
+ if (proxySettings.SecureProxy.empty() && !proxySettings.Proxy.empty())
4109
+ {
4110
+ environment.emplace_back(std::format("{}={}", c_httpsProxyLower, proxySettings.Proxy));
4111
+ environment.emplace_back(std::format("{}={}", c_httpsProxyUpper, proxySettings.Proxy));
4112
+ }
4113
}
4114
}
4115
CATCH_LOG()
test/windows/NetworkTests.cpp
+47
-5
@@ -1044,10 +1044,10 @@ class NetworkTests
1044
1045
static void ClearHttpProxySettings(bool userScope)
1046
{
1047
- auto command = L"Set-WinhttpProxy -SettingScope Machine -Proxy \\\"\\\"";
1047
+ auto command = L"Set-WinhttpProxy -SettingScope Machine -Proxy \\\"\\\" -AutoconfigUrl \\\"\\\"";
1048
if (userScope)
1049
{
1050
- command = L"Set-WinhttpProxy -SettingScope User -Proxy \\\"\\\"";
1050
+ command = L"Set-WinhttpProxy -SettingScope User -Proxy \\\"\\\" -AutoconfigUrl \\\"\\\"";
1051
}
1052
LxsstuLaunchPowershellAndCaptureOutput(command);
1053
}
@@ -1087,7 +1087,8 @@ class NetworkTests
1087
static constexpr auto c_proxyBypassLower = L"no_proxy";
1088
static constexpr auto c_proxyBypassUpper = L"NO_PROXY";
1089
static constexpr auto c_pacProxy = L"WSL_PAC_URL";
1090
- static constexpr auto c_httpProxyString = L"http://test.com:8888";
1090
+ static constexpr auto c_httpProxyHostPort = L"test.com:8888";
1091
+ static inline const std::wstring c_httpProxyString = std::wstring(L"http://") + c_httpProxyHostPort;
1092
static constexpr auto c_httpProxyString2 = L"http://otherServer.com:1234";
1093
static constexpr auto c_httpProxyLocalhost = L"http://localhost:8888";
1094
static constexpr auto c_httpProxyLoopback = L"http://loopback:8888";
@@ -1096,7 +1097,10 @@ class NetworkTests
1097
static constexpr auto c_httpProxyIpV4 = L"http://198.168.1.128:8888";
1098
static constexpr auto c_httpProxyIpV6 = L"http://[2001::1]:8888";
1099
static constexpr auto c_httpProxyBypassString = L"test";
1099
- static constexpr auto c_httpProxyPACurl = L"testpac.pac";
1100
+ static constexpr auto c_pacServerPrefix = L"http://127.0.0.1:12399/";
1101
+ static constexpr auto c_pacUrl = L"http://127.0.0.1:12399/wslproxy.pac";
1102
+ static inline const std::wstring c_pacScript =
1103
+ std::wstring(LR"(function FindProxyForURL(url, host) { return \"PROXY )") + c_httpProxyHostPort + LR"(\"; })";
1104
1105
static void VerifyWslEnvVariable(const std::wstring& envVar, const std::wstring& proxyString)
1106
{
@@ -1174,7 +1178,7 @@ class NetworkTests
1178
THROW_LAST_ERROR_IF(!SetEnvironmentVariable(L"WSLENV", nullptr));
1179
});
1180
1177
- THROW_LAST_ERROR_IF(!SetEnvironmentVariable(c_httpProxyLower, c_httpProxyString));
1181
+ THROW_LAST_ERROR_IF(!SetEnvironmentVariable(c_httpProxyLower, c_httpProxyString.c_str()));
1182
std::wstring wslEnvVal{c_httpProxyLower};
1183
THROW_LAST_ERROR_IF(!SetEnvironmentVariable(L"WSLENV", wslEnvVal.append(L"/u").c_str()));
1184
@@ -1270,6 +1274,27 @@ class NetworkTests
1274
VerifyHttpProxyFilterByNetworkConfiguration(false);
1275
}
1276
1277
+ static void VerifyHttpProxyPac(bool userScope = true)
1278
+ {
1279
+ UniqueWebServer pacServer(c_pacServerPrefix, c_pacScript.c_str());
1280
+
1281
+ auto restoreProxySettings = wil::scope_exit([&] { ClearHttpProxySettings(userScope); });
1282
+
1283
+ SetHttpProxySettings(L"", L"", c_pacUrl, userScope);
1284
+
1285
+ // The update race condition is more likely to trigger for PAC as there is an additional http round trip.
1286
+ wsl::shared::retry::RetryWithTimeout<void>(
1287
+ [&]() {
1288
+ auto [out, _] = LxsstuLaunchWslAndCaptureOutput(std::wstring(L"echo -n $") + c_httpProxyLower);
1289
+ THROW_HR_IF(E_FAIL, out != c_httpProxyString);
1290
+ },
1291
+ std::chrono::seconds(1),
1292
+ std::chrono::minutes(2));
1293
+
1294
+ VerifyHttpProxyPacUrlMirrored(c_pacUrl);
1295
+ VerifyHttpProxyStringMirrored(c_httpProxyString);
1296
+ }
1297
+
1298
WSL2_TEST_METHOD(NatHttpProxyVerifyConfigDisabled)
1299
{
1300
WINHTTP_PROXY_TEST_ONLY();
@@ -1333,6 +1358,13 @@ class NetworkTests
1358
VerifyHttpProxyFilterByNetworkConfigurationNAT();
1359
}
1360
1361
+ WSL2_TEST_METHOD(NatHttpProxyPac)
1362
+ {
1363
+ WINHTTP_PROXY_TEST_ONLY();
1364
+ WslConfigChange config(LxssGenerateTestConfig({.autoProxy = true}));
1365
+ VerifyHttpProxyPac();
1366
+ }
1367
+
1368
WSL2_TEST_METHOD(RenameInterface)
1369
{
1370
// Disconnect "eth0" interface so it can be renamed
@@ -3868,6 +3900,16 @@ class MirroredTests
3900
NetworkTests::VerifyHttpProxyFilterByNetworkConfigurationMirrored();
3901
}
3902
3903
+ WSL2_TEST_METHOD(HttpProxyPac)
3904
+ {
3905
+ MIRRORED_NETWORKING_TEST_ONLY();
3906
+ WINHTTP_PROXY_TEST_ONLY();
3907
+
3908
+ m_config->Update(LxssGenerateTestConfig({.networkingMode = wsl::core::NetworkingMode::Mirrored, .autoProxy = true}));
3909
+ WaitForMirroredStateInLinux();
3910
+ NetworkTests::VerifyHttpProxyPac();
3911
+ }
3912
+
3913
WSL2_TEST_METHOD(SmokeTest)
3914
{
3915
MIRRORED_NETWORKING_TEST_ONLY();