Как использовать 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).