Skip to content

API Proposal: size of http response headers #31003

Closed
@zivkan

Description

@zivkan

Rationale and Usage

Download managers, or other applications that wish to closely monitor network performance, when using HttpClient may be interested in the number of bytes a response header was, in order to calculate a bytes/second metric from that HTTP server. Right now the best we can do count the bytes of the response's content stream, but responses with no body are treated as zero bytes transferred, despite the fact that it did indeed transfer bytes over the network.

Here's a simplistic example of what I'd like to be able to do:

var requestTime = Stopwatch.StartNew();
var headerTime = Stopwatch.StartNew();
var response = client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
headerTime.Stop();

var responseData = await response.Content.ReadAsByteArrayAsync();
requestTime.Stop();

networkTelemetry.OnComplete(request.RequestUri, headerTime.Elapsed, response.HeaderBytesTransferred, responseTime.Elapsed, responseData.Length);

I work on NuGet and due to the design on how it works, we expect a large number of our requests to return 404's. Therefore not being able to take into account header size impacts our ability to better understand our own network usage, or the network connectivity of the customer's machine to the host it's trying to download from.

Proposed API

I'd like the input of experts in the area, as I'm not sure where this would go, assuming the concept is agreeable.

One possibility is to add a Size property to HttpResponseHeaders, however, this makes it sound like there was a header returned with the name "Size". So it doesn't feel right to me.

Another possibility is to add a HeaderSize property to HttpResponseMessage, but it also feels a bit out of place.

A third option is along the lines of #31000, but rather than having position set to zero at the start of the body, the position is zero before headers are read and the position when HttpClient.SendAsync returns determines the size of the headers. The position once the full body has been read is therefore the body size plus the header size. For example:

var response = client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
var stream = await response.Content.ReadAsStreamAsync();
var headerSize = stream.Position;
await ProcessStreamToEnd(stream);
var bodySize = stream.Position - headerSize;

Open Questions

Unfortunately I'm not an expert in the HTTP protocol. My understanding is that with HTTP 1.x, response headers are not compressed, but with HTTP 2.0 they will be. Therefore there is a question if the header size should be the number of bytes before of after decompression. Since I am interested in measuring the network connectivity to the HTTP host, I would prefer the compressed size, which would give a more consistent result, regardless of whether the header was highly or poorly compressible for a particular response.

I assume that TLS streams are the same size encrypted and decrypted and therefore they hopefully won't complicate the issue further.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions