Как использовать Fiddler с HttpClient?

Я знаю, что есть много вопросов/ответов, блоги об этом, не говоря о часто задаваемых вопросах Telerik. Тем не менее я не мог найти этот диагноз и решить чистым образом:

Контекст:

У меня есть приложение Web API, и у меня есть клиент (unit test), который использует HttpClient для отправки запросов API. Приложение Web API прослушивает http://localhost:8631/ Иногда я использую Fiddler, чтобы узнать, что происходит.

Вопрос:

Трафик между моим HttpClient и веб-API не фиксируется Fiddler. После запуска трафика Fiddler все еще в порядке, но не отображается в Fiddler.

Диагностика:

  • Важно: Использование любого браузера и отправка запросов http://localhost:8631/ работает, я имею в виду: трафик, захваченный Fiddler
  • Настройка HttpClient явно для использования Fiddler как прокси-сервера не помогает.
  • Изменение URL-адреса HttpClient от http://localhost:8631/ до http://localhost .fiddler: 8631/ помогает, независимо от того, был ли настроен прокси-сервер или нет.

Выводы: По крайней мере, мой случай: дело не в том, что HttpClient явно настроен на использование Fiddler в качестве прокси-сервера или нет. Это касается поведения HttpClient и/или Fiddler localhost.

Проблема снова:

Можно спросить: проблема решена, тогда в чем вопрос? Ну...

Q1: Это все еще проблема, потому что URL-адрес закодирован или сконфигурирован где-то (я имею в виду http://localhost:8631/ или http://localhost .fiddler: 8631, чтобы каждый запуск и остановка скрипача его необходимо обновлять. Подробнее: проверка в источник для источника управления, а также проверка на другом компьютере товарищем по команде может вызвать проблему. Итак: есть ли менее болезненное обходное решение для этого?

Жесткое кодирование имени моей машины (которое также может работать) вызывает ту же боль и проблему при работе в команде и использовании источника управления

Q2: Почему это непоследовательное поведение: Pure http://localhost:8631/ работает из любого браузера, но не из HttpClient.

Я думаю, что ответ Q2 может приблизиться к более удобному обходному пути.

Экспортировать код

    // 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)
        };
        // ...

Ответ 1

Проблема заключается в том, что реализация Microsoft класса WebProxy имеет статическую проверку для ссылок на loopback (на основе списка имен, таких как "localhost" ), и будет обходить любой прокси-адрес для uris, идентифицированного как loopback. Даже настройка BypassProxyOnLocal не имеет значения. Этот параметр действует только в том случае, если вы используете имя локальной машины или другое имя компьютера в локальной сети. Локальный хост хоста или IP-адрес 127.0.0.1 всегда классифицируются как loopback и приводят к обходу прокси-сервера.

Соответствующая часть кода рамки .net находится в WebProxy.IsBypassedManual:

if (host.IsLoopback) {
    return true; // bypass localhost from using a proxy.
}

Напишите свой собственный потомок класса WebProxy и перезапишите методы GetProxy и IsBypassed, чтобы вернуть uri, используя прокси, даже для URL-адресов обратной петли. Затем присвойте экземпляр этого класса HttpClientHandler, который вы используете для создания HttpClient.

Кажется, что не работает, потому что код .net ожидает работы с объектами, реализующими IAutoWebProxy, но IAutoWebProxy объявляется внутренним и не может использоваться в нашем собственном коде.

Самое легкое решение, которое я вижу, - это функция, которая заменяет "localhost" локальным именем компьютера в ApiUrl во время выполнения. Имя локальной машины будет работать независимо от того, работает ли Fiddler или нет.

Ответ 2

Просто укажите прокси-сервер по умолчанию для вашего экземпляра HttpClient, и он работает как шарм. Вам не нужно менять какой-либо URL в вашем коде.

HttpClientHandler handler = new HttpClientHandler( );
handler.Proxy = WebRequest.DefaultWebProxy;
HttpClient client = new HttpClient( handler as HttpMessageHandler );

Мы используем одно и то же поведение без каких-либо проблем (Windows 10, Fiddler4).