runtime: WebRequest.DefaultWebProxy not compatible with HttpClient

If I have the following HttpClient:

var handler = new HttpClientHandler();
handler.UseDefaultCredentials = true;
handler.Proxy = WebRequest.DefaultWebProxy;
var client = new HttpClient(handler);
client.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "Mozilla/5.0 Bla")

The first time I use this client (with client.GetAsync("http://www.nuget.org/api/v2")), I will get back the correct result. However, if I reuse the client, I will get an exception:

System.PlatformNotSupportedException: Operation is not supported on this platform.
                            at System.Net.SystemWebProxy.IsBypassed(Uri host)
                            at System.Net.Http.WinHttpHandler.SetRequestHandleProxyOptions(RequestState state)
                            at System.Net.Http.WinHttpHandler.SetRequestHandleOptions(RequestState state)
                            at System.Net.Http.WinHttpHandler.<StartRequest>d__1.MoveNext()

Is this a bug on CoreClr? Do I have to create new instance of HttpClient everytime?

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 29 (16 by maintainers)

Most upvoted comments

There are a lot of issues with providing the “SystemProxy” wrapper. Proxy discovery and evaluation of the registry settings can involve network operation such as WPAD protocol to find a PAC file. Then that PAC file (a JavaScript file) needs to be evaluated. We used to do that JavaScript evaluation in the .NET Framework but discovered it impacted performance due to hosting the interpreter. Over time, that functionality was delegated (on Windows) to the WinHTTP AutoProxy Discover background service which would do that evaluation for our Http stack and cache the information for other process to use. That improved performance and security. But, therefore, that evaluation is not publicly surfaced, but only used by the internal HTTP stacks.

So, bottom line, we no longer support that functionality which is one reason we don’t have the concrete WebProxy class in CoreFx anymore.

@Gladskih Please do not comment or ask questions about closed issues. They are seldom monitored. If you have a bug or question , please open a new issue.

With respect to your question, you can pass credentials (including default credentials) to the system default proxy using the following code:

var handler = new HttpClientHandler();
handler.DefaultProxyCredentials = CredentialCache.DefaultCredentials;
var client = new HttpClient(handler);

@StevenLiekens Thank you for clarifying your requirements.

Since you appear to want to access WebProxy class separately, it is possible that the functionality you want can be implemented in .NET Core.

My comments above and this particular issue dealt with an interaction between HttpClient and WebProxy. That interaction doesn’t work the same anymore since the HttpClient stack uses OS specific stacks.

But WebProxy itself can be enhanced by implementing the functionality on both Windows and Linux to read the operating system proxy settings. I want to point out that reading the system proxy settings isn’t sufficient to return a proxy URL given a destination URL. Simple proxy settings can be static, i.e. a single proxy URL for all destination URLs. But proxy settings on Windows, for example, can involve WPAD protocol to find a PAC file (Javascript file) that then has to be evaluated using a Javascript engine and the functions in that Javascript called to evaluate the correct proxy URL.

Even in pure managed HTTP stacks such as the .NET Framework, we stopped doing Javascript evaluation of the PAC file because it is risky. Instead, we switched over the years to using OS services to run the Javascript evaluation out of process using Win32 APIs with WinHttp AutoProxy Service. I am not sure whether Linux supports this type of proxy evaluation.

Since the .NET Core stacks used OS level HTTP APIs, that mean it evaluated proxy URLs automatically (under the covers) and so we didn’t need to implement the WebProxy class fully in .NET Core.

I would recommend you open a new issue and request that the WebProxy class be implemented more fully so that it can resolve and evaluate system level proxy settings and return a proxy URL given all the system settings and a destination URL.

And one final thing…WebRequest.DefaultWebProxy will only return the “system” proxy if you haven’t set that property to something else.

So, code like this will cause WebRequest.DefaultWebProxy to return a custom proxy.

IWebProxy myProxy = new CustomProxy();
WebRequest.DefaultWebProxy = myProxy;

/// future get of the DefaultWebProxy property will return myProxy and not the system proxy.

is there a way to get to the system proxy info via HttpClientHandler?

No. The HTTP stacks in .NET Core use the OS level HTTP stacks. This is true for both Windows and Linux. While we can specify that a request can USE the system proxy, we cannot query the system to determine what that system proxy is. Usually this isn’t needed. It’s more important that HTTP requests can use the system proxy and that developers can specify to use the system proxy or a custom proxy. But unfortunately, you cannot read the system proxy settings themselves.

@karelz I think it’s unfortunate that there is no way to get the address of the system proxy. I don’t particularly care that the WebRequest API went away. I care because that was the only way to get that information.

We don’t support that in CoreFx directly. We don’t have a “SystemProxy” wrapper for IWebProxy anymore. Part of the ‘WebProxy’ class in .NET Framework did that. But we don’t support that now.

However, usually you don’t need that information directly. Usually, it’s only the Http stack itself that needs that information in order to send your request to its final destination.

So, I’m curious as to how you are using the returned ‘proxyUrl’ information in your app?

I don’t quite follow your question. Why do you need a “wrapped” IWebProxy? And by that, I think you mean, have a public concrete class that implements IWebProxy interface.

Can you show some example C# code of a coding pattern you use where you used to use WebProxy and/or WebRequest.DefaultWebProxy? Then I could probably explain what new coding pattern to use instead.

As I mentioned, you should be able to just use HttpClientHandler as-is and it will discover proxy information in the registry settings and apply them as needed for outgoing http requests.

does it mean that on .NET Framework (Desktop), if the default value of HttpClientHandler.Proxy is null, then HttpClientHandler will use IE proxy settings?

Yes, for both .NET Framework and CoreFx, that is true for HttpClientHandler defaults.