I know there are many of questions/answers, blogs about this, not talking about Telerik's FAQ. Still I could not find this diagnosed and solved in a clear pure way:
Context:
I have a Web API app, and I have a (unit test) client, which uses HttpClient to send requests to the API. Web API app listens in http://localhost:8631/ Sometimes I use Fiddler to see what's going on.
Issue:
Traffic between my HttpClient and Web API is not captured by Fiddler. After launching Fiddler traffic is still OK, but not shown in Fiddler.
Diagnostics so far:
Conclusions: At least my case: It is not about HttpClient is configured explicitly to using Fiddler as proxy or not. It is about HttpClient's and/or Fiddler's localhost behaviour.
Issue again:
One may ask: Problem solved, then what is the question? Well...
Q1: This is still a painful issue, because the url is coded or configured somewhere (I mean http://localhost:8631/ or http://localhost.fiddler:8631 so every start and stop of fiddler it must be updated. More: Checking in the source to source control, and checking out on an other machine by a teammate may cause issue. So: Is there any less painful workaround for this?
Hard coding my machine name (which also could work) causes the very same pain and issue when working in a team and using source control
Q2: Why is this inconsistent behaviour: Pure http://localhost:8631/ works from any browser but not from HttpClient.
I think answering Q2 can get us closer to a more usable workaround.
Code Exhibit
// Using the following url w o r k s regardless of any proxy setting
// ...but it is a pain to hardcode or configure this and change depending on Fiddler is running or not
//private const string ApiUrl = "http://localhost.fiddler:8631/";
// This is not working regardless any proxy setting. Trafic bypasses Fiddler
private const string ApiUrl = "http://localhost:8631/";
protected HttpClient GetClient()
{
var httpClientHandler = new HttpClientHandler
{
// Does not work
//Proxy = new WebProxy("http://localhost:8888", false),
// Does not work
Proxy = WebRequest.DefaultWebProxy,
UseProxy = true
};
var client = new HttpClient(httpClientHandler)
{
BaseAddress = new Uri(ApiUrl)
};
// ...
The problem is that the Microsoft implementation of the WebProxy
class has a static check for loopback urls (based on a list of names like "localhost") and will bypass any proxy for uris identified as loopback. Even the BypassProxyOnLocal
setting will not matter. This setting only has an effect if you use the local machine name or another machine name in the local network. The host localhost or the ip address 127.0.0.1 are always recogized as loopback and will lead to bypassing the proxy.
Relevant part of the .net framework code is in WebProxy.IsBypassedManual
:
if (host.IsLoopback) {
return true; // bypass localhost from using a proxy.
}
Write your own descendant of the WebProxy class and overwrite the GetProxy
and IsBypassed
methods to return an uri using the proxy even for loopback urls. Then assign an instance of that class to the HttpClientHandler
you use to create the HttpClient
.
Doesn't seem to work because the .net code expects to work with objects that implement IAutoWebProxy, but IAutoWebProxy is declared internal and cannot be used in our own code.
The easiest solution I see is to have a feature that replaces "localhost" with the local machine name in ApiUrl at runtime. The local machine name will work regardless of whether Fiddler is running or not.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With