@@ -297,7 +297,7 @@ static DWORD ChooseAuthScheme( DWORD dwSupportedSchemes )
297
297
return 0 ;
298
298
}
299
299
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
301
301
// properly freed.
302
302
struct proxy_info : WINHTTP_PROXY_INFO
303
303
{
@@ -315,6 +315,24 @@ struct proxy_info : WINHTTP_PROXY_INFO
315
315
}
316
316
};
317
317
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
+
318
336
// WinHTTP client.
319
337
class winhttp_client : public _http_client_communicator
320
338
{
@@ -376,8 +394,13 @@ class winhttp_client : public _http_client_communicator
376
394
// Open session and connection with the server.
377
395
virtual unsigned long open () override
378
396
{
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
+
379
401
DWORD access_type;
380
402
LPCWSTR proxy_name;
403
+ LPCWSTR proxy_bypass = WINHTTP_NO_PROXY_BYPASS;
381
404
utility::string_t proxy_str;
382
405
http::uri uri;
383
406
@@ -388,10 +411,51 @@ class winhttp_client : public _http_client_communicator
388
411
access_type = WINHTTP_ACCESS_TYPE_NO_PROXY;
389
412
proxy_name = WINHTTP_NO_PROXY_NAME;
390
413
}
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 ())
392
454
{
393
455
access_type = WINHTTP_ACCESS_TYPE_DEFAULT_PROXY;
394
456
proxy_name = WINHTTP_NO_PROXY_NAME;
457
+
458
+ m_proxy_auto_config = true ;
395
459
}
396
460
else
397
461
{
@@ -426,7 +490,7 @@ class winhttp_client : public _http_client_communicator
426
490
NULL ,
427
491
access_type,
428
492
proxy_name,
429
- WINHTTP_NO_PROXY_BYPASS ,
493
+ proxy_bypass ,
430
494
WINHTTP_FLAG_ASYNC);
431
495
if (!m_hSession)
432
496
{
@@ -513,13 +577,22 @@ class winhttp_client : public _http_client_communicator
513
577
proxy_info info;
514
578
bool proxy_info_required = false ;
515
579
516
- if ( client_config (). proxy (). is_auto_discovery () )
580
+ if (m_proxy_auto_config )
517
581
{
518
582
WINHTTP_AUTOPROXY_OPTIONS autoproxy_options;
519
583
memset ( &autoproxy_options, 0 , sizeof (WINHTTP_AUTOPROXY_OPTIONS) );
520
584
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
+
523
596
autoproxy_options.fAutoLogonIfChallenged = TRUE ;
524
597
525
598
auto result = WinHttpGetProxyForUrl (
@@ -1370,6 +1443,12 @@ class winhttp_client : public _http_client_communicator
1370
1443
HINTERNET m_hSession;
1371
1444
HINTERNET m_hConnection;
1372
1445
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;
1373
1452
};
1374
1453
1375
1454
std::shared_ptr<_http_client_communicator> create_platform_final_pipeline_stage (uri&& base_uri, http_client_config&& client_config)
0 commit comments