@@ -297,7 +297,7 @@ static DWORD ChooseAuthScheme( DWORD dwSupportedSchemes )
297297 return 0 ;
298298}
299299
300- // Small RAII helper to ensure that the fields of this struct are always
300+ // Small RAII helpers to ensure that the fields of these structs are always
301301// properly freed.
302302struct proxy_info : WINHTTP_PROXY_INFO
303303{
@@ -315,6 +315,24 @@ struct proxy_info : WINHTTP_PROXY_INFO
315315 }
316316};
317317
318+ struct ie_proxy_config : WINHTTP_CURRENT_USER_IE_PROXY_CONFIG
319+ {
320+ ie_proxy_config ()
321+ {
322+ memset ( this , 0 , sizeof (WINHTTP_CURRENT_USER_IE_PROXY_CONFIG) );
323+ }
324+
325+ ~ie_proxy_config ()
326+ {
327+ if ( lpszAutoConfigUrl )
328+ ::GlobalFree (lpszAutoConfigUrl);
329+ if ( lpszProxy )
330+ ::GlobalFree (lpszProxy);
331+ if ( lpszProxyBypass )
332+ ::GlobalFree (lpszProxyBypass);
333+ }
334+ };
335+
318336// WinHTTP client.
319337class winhttp_client : public _http_client_communicator
320338{
@@ -376,8 +394,13 @@ class winhttp_client : public _http_client_communicator
376394 // Open session and connection with the server.
377395 virtual unsigned long open () override
378396 {
397+ // This object have lifetime greater than proxy_name and proxy_bypass
398+ // which may point to its elements.
399+ ie_proxy_config proxyIE;
400+
379401 DWORD access_type;
380402 LPCWSTR proxy_name;
403+ LPCWSTR proxy_bypass = WINHTTP_NO_PROXY_BYPASS;
381404 utility::string_t proxy_str;
382405 http::uri uri;
383406
@@ -388,10 +411,51 @@ class winhttp_client : public _http_client_communicator
388411 access_type = WINHTTP_ACCESS_TYPE_NO_PROXY;
389412 proxy_name = WINHTTP_NO_PROXY_NAME;
390413 }
391- else if (config.proxy ().is_default () || config.proxy ().is_auto_discovery ())
414+ else if (config.proxy ().is_default ())
415+ {
416+ // Use the default WinHTTP proxy by default.
417+ access_type = WINHTTP_ACCESS_TYPE_DEFAULT_PROXY;
418+ proxy_name = WINHTTP_NO_PROXY_NAME;
419+
420+ // However, if it is not configured...
421+ proxy_info proxyDefault;
422+ if (!WinHttpGetDefaultProxyConfiguration (&proxyDefault) ||
423+ proxyDefault.dwAccessType == WINHTTP_ACCESS_TYPE_NO_PROXY)
424+ {
425+ // ... then try to fall back on the default WinINET proxy, as
426+ // recommended for the desktop applications (if we're not
427+ // running under a user account, the function below will just
428+ // fail, so there is no real need to check for this explicitly)
429+ if (WinHttpGetIEProxyConfigForCurrentUser (&proxyIE))
430+ {
431+ if (proxyIE.fAutoDetect )
432+ {
433+ m_proxy_auto_config = true ;
434+ }
435+ else if (proxyIE.lpszAutoConfigUrl )
436+ {
437+ m_proxy_auto_config = true ;
438+ m_proxy_auto_config_url = proxyIE.lpszAutoConfigUrl ;
439+ }
440+ else if (proxyIE.lpszProxy )
441+ {
442+ access_type = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
443+ proxy_name = proxyIE.lpszProxy ;
444+
445+ if (proxyIE.lpszProxyBypass )
446+ {
447+ proxy_bypass = proxyIE.lpszProxyBypass ;
448+ }
449+ }
450+ }
451+ }
452+ }
453+ else if (config.proxy ().is_auto_discovery ())
392454 {
393455 access_type = WINHTTP_ACCESS_TYPE_DEFAULT_PROXY;
394456 proxy_name = WINHTTP_NO_PROXY_NAME;
457+
458+ m_proxy_auto_config = true ;
395459 }
396460 else
397461 {
@@ -426,7 +490,7 @@ class winhttp_client : public _http_client_communicator
426490 NULL ,
427491 access_type,
428492 proxy_name,
429- WINHTTP_NO_PROXY_BYPASS ,
493+ proxy_bypass ,
430494 WINHTTP_FLAG_ASYNC);
431495 if (!m_hSession)
432496 {
@@ -513,13 +577,22 @@ class winhttp_client : public _http_client_communicator
513577 proxy_info info;
514578 bool proxy_info_required = false ;
515579
516- if ( client_config (). proxy (). is_auto_discovery () )
580+ if (m_proxy_auto_config )
517581 {
518582 WINHTTP_AUTOPROXY_OPTIONS autoproxy_options;
519583 memset ( &autoproxy_options, 0 , sizeof (WINHTTP_AUTOPROXY_OPTIONS) );
520584
521- autoproxy_options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
522- autoproxy_options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A;
585+ if (m_proxy_auto_config_url.empty ())
586+ {
587+ autoproxy_options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
588+ autoproxy_options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A;
589+ }
590+ else
591+ {
592+ autoproxy_options.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL;
593+ autoproxy_options.lpszAutoConfigUrl = m_proxy_auto_config_url.c_str ();
594+ }
595+
523596 autoproxy_options.fAutoLogonIfChallenged = TRUE ;
524597
525598 auto result = WinHttpGetProxyForUrl (
@@ -1370,6 +1443,12 @@ class winhttp_client : public _http_client_communicator
13701443 HINTERNET m_hSession;
13711444 HINTERNET m_hConnection;
13721445 bool m_secure;
1446+
1447+ // If auto config is true, dynamically find the proxy for each URL using
1448+ // the proxy configuration script at the given URL if it's not empty or
1449+ // using WPAD otherwise.
1450+ bool m_proxy_auto_config{false };
1451+ utility::string_t m_proxy_auto_config_url;
13731452};
13741453
13751454std::shared_ptr<_http_client_communicator> create_platform_final_pipeline_stage (uri&& base_uri, http_client_config&& client_config)
0 commit comments