Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Fiddler with HttpClient?

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:

  • Important: Using any browser and sending requests to http://localhost:8631/ is working, I mean: traffic captured by Fiddler
  • Configuring HttpClient explicitly to use Fiddler as proxy does not help.
  • Changing HttpClient url from http://localhost:8631/ to http://localhost.fiddler:8631/ helps, regardless of proxy was configured or not.

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)
        };
        // ...
like image 936
g.pickardou Avatar asked Mar 29 '16 06:03

g.pickardou


Video Answer


1 Answers

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.

like image 143
NineBerry Avatar answered Sep 17 '22 12:09

NineBerry