Http request broken after upgrading to .NET Core 2.1

Viewed 562

I'm posting telemetry data to the Application Insights data collector endpoint at https://dc.services.visualstudio.com/v2/track using HttpClient.

This works fine when using .NET Core 2.0. However, after upgrading to .NET Core 2.1 all requests fail with HTTP status 500 Internal Server Error and an HTML response body that looks like this:

IIS 8.5 Detailed Error

(It's an IIS 8.5 Detailed Error page)

In .NET Core 2.1 they have changed how HttpClientHandler works and added an AppContext switch that allows us to keep the old behavior:

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

Indeed, setting this switch fixes the problem!

But I'd like to avoid using that switch:

  • Firstly, because I'd like to use the new stuff. It must be better :-)
  • Secondly, because that switch changes behavior for all new HttpClientHandler instances. Not just the one I'm using to post data to the Application Insights endpoint.

I've tried to figure out what's causing this by looking at the traffic using Wireshark. Trying to interpret HTTPS traffic on that low level is beyond me. I did find something suspicious in the TLS handshake though.

Both the SocketsHttpHandler (that doesn't work) and the legacy WinHttpHandler (that do work) use TLS 1.2. However, only the WinHttpHandler uses the TLS Certificate Status Request extension. Could that be the reason why requests are failing?

In any case, the TLS connection is setup a request is sent and a response is retrieved. And apparently there is an error on the server side while processing the request.

I'd like to figure out what's causing this problem. Any help is appreciated!


As suggested by @mjwills I changed my code so that it uses HTTP (not SSL) and post to a local program that allows me to capture the request. (I didn't figure out how to do this in a clean way in Wireshark, so I ended up writing my own little capture tool based on TcpListener):

Capture when using the new 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

Capture when using the legacy 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

These are the differences:

  • WinHttpHandler wants to keep the connection alive while SocketsHttpHandler does not.

  • WinHttpHandler use lower case hex for chunk lengths while SocketsHttpHandler use upper case.

The first 10 bytes contains the gzip header. The remaining 244 bytes contains the gzip encoded json telemetry data.

0 Answers
Related