Http-запрос не работает после обновления до .NET Core 2.1 - PullRequest
0 голосов
/ 01 ноября 2018

Я отправляю данные телеметрии в конечную точку сборщика данных Application Insights на https://dc.services.visualstudio.com/v2/track, используя HttpClient.

Это прекрасно работает при использовании .NET Core 2.0. Однако после обновления до .NET Core 2.1 все запросы не выполняются со статусом HTTP 500 Internal Server Error и текстом ответа HTML, который выглядит следующим образом:

IIS 8.5 Detailed Error

( Это страница подробных ошибок IIS 8.5 )

В .NET Core 2.1 они изменили , как HttpClientHandler работает, и добавили переключатель AppContext, который позволяет нам сохранить старое поведение:

AppContext.SetSwitch("System.Net.Http.UseSocketsHttpHandler", false);

Действительно, установка этого переключателя устраняет проблему!

Но я бы хотел не использовать этот переключатель:

  • Во-первых, потому что я хотел бы использовать новый материал. Это должно быть лучше: -)
  • Во-вторых, потому что этот переключатель изменяет поведение для всех новых HttpClientHandler экземпляров. Не только тот, который я использую для публикации данных в конечной точке Application Insights.

Я попытался выяснить причину этого, посмотрев на трафик с помощью Wireshark. Попытка интерпретировать HTTPS-трафик на этом низком уровне мне не по силам. Я нашел что-то подозрительное в рукопожатии TLS.

И SocketsHttpHandler (который не работает), и устаревший WinHttpHandler (который работает) используют TLS 1.2. Однако только WinHttpHandler использует расширение запроса статуса сертификата TLS . Может ли это быть причиной того, что запросы не выполняются?

В любом случае, соединение TLS настроено, запрос отправляется и ответ получен. И, видимо, при обработке запроса на стороне сервера произошла ошибка.

Я бы хотел выяснить, что является причиной этой проблемы. Любая помощь приветствуется!


Как подсказал @mjwills, я изменил свой код, чтобы он использовал HTTP (не SSL) и отправлял сообщения в локальную программу, которая позволяет мне перехватить запрос. (Я не придумал, как сделать это в Wireshark чисто, поэтому в итоге я написал свой собственный маленький инструмент захвата, основанный на TcpListener):

Захват при использовании нового SocketsHttpHandler:

POST / HTTP/1.1
Transfer-Encoding: chunked
Content-Type: application/x-json-stream
Content-Encoding: gzip
Host: localhost:12345

A
[...10 bytes of data...]
F4
[...244 bytes of data...]
0

Захват при использовании устаревшего WinHttpHandler:

POST / HTTP/1.1
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/x-json-stream
Content-Encoding: gzip
Host: localhost:12345

a
[...10 bytes of data...]
f4
[...244 bytes of data...]
0

Вот различия:

  • WinHttpHandler хочет сохранить соединение, а SocketsHttpHandler - нет.

  • WinHttpHandler используйте шестнадцатеричный регистр для длин порций, в то время как SocketsHttpHandler используйте верхний регистр.

Первые 10 байтов содержат заголовок gzip. Оставшиеся 244 байта содержат данные телеметрии JSON в кодировке gzip.

...