Content-Length header not always returned when enumerating HttpContentHeaders - #102416
Conversation
|
Forcing the computation in the constructor is too early, derived types may not even get a chance to initialize. Consider this example. With this change, public sealed class FileHttpContent : HttpContent
{
private readonly string _path;
public FileHttpContent(string path)
{
Headers.Add("X-File-Name", Uri.EscapeDataString(Path.GetFileName(path)));
_path = path;
}
protected override Task SerializeToStreamAsync(Stream stream, TransportContext context) =>
SerializeToStreamAsync(stream, context, CancellationToken.None);
protected override async Task SerializeToStreamAsync(Stream stream, TransportContext context, CancellationToken cancellationToken)
{
await using FileStream fs = File.OpenRead(_path);
await fs.CopyToAsync(stream, cancellationToken);
}
protected override bool TryComputeLength(out long length)
{
length = new FileInfo(_path).Length;
return true;
}
}If we want to force the value to be available during enumeration, we should force its creation when trying to enumerate and not before. |
|
That means I need to overload GetEnumerator in HttpContentHeaders. Will this need an api review ? |
|
These are all internal implementation details, we shouldn't need to make API changes. |
|
Sorry if I'm asking too much questions, but HttpHeaders & HttpHeadersNonValidated do not know about HttpContent nor its length. I don't see how updating GetEnumerator in these two classes would help. |
|
What I mean is that where the public IEnumerator<KeyValuePair<string, IEnumerable<string>>> GetEnumerator() =>
GetEnumeratorCore();it could instead be public IEnumerator<KeyValuePair<string, IEnumerable<string>>> GetEnumerator()
{
if (this is HttpContentHeaders contentHeaders)
{
_ = contentHeaders.ContentLength;
}
return GetEnumeratorCore();
} |
MihaZupan
left a comment
There was a problem hiding this comment.
Thank you for looking into these issues.
Thinking about it a bit more, this would still run into the issue mentioned in #102416 (comment) if the implementation tried enumerating the headers from its constructor (e.g. replace Headers.Add with Headers.ToString()).
While I doubt that's all that common, it feels too risky to just break.
We could go with just A) mentioned here: #16162 (comment)
That is, only fix the issue for built-in types.
The test |
Do I make |
|
I was thinking it may be as simple as |
MihaZupan
left a comment
There was a problem hiding this comment.
Thanks.
ReadOnlyMemoryContent looks like another place where this could be applied
…tHeaders (dotnet#102416) * Content-Length header not always returned when enumerating HttpContentHeaders * fix failing unit test * make loading ContentLength part of HttpHeaders and HttpHeadersNonValidated * rework * initialize content length in ReadOnlyMemoryContent ctor
|
Should HttpClient be removing/throwing if
https://www.rfc-editor.org/rfc/rfc9112#section-6.2-2
Noticed this because one of our tests is failing due to this update and it is also explicitly setting chunked transfer encoding |
|
We do that validation at the I'm guessing your test is skipping that since you have a custom handler? |
|
Ah ok, good to know |
…tpContentHeaders (dotnet#102416)" This reverts commit d9d0e38.
Fixes #16162