Skip to content

VKV can't parse KV when reading directly from HttpClient's stream using HttpCompletionOption.ResponseHeadersRead #48

@JustArchi

Description

@JustArchi

HttpCompletionOption.ResponseHeadersRead is a special option we can pass to HttpClient which allows to return the response as soon as 200 OK is returned (as opposed to full data), which allows the user to start parsing the data while it's still being buffered.

A repro below:

private static async Task ReproNotWorking() {
    using HttpClient httpClient = new();

    using HttpRequestMessage request = new(HttpMethod.Get, new Uri("https://raw.githubusercontent.com/SteamDatabase/GameTracking-CSGO/master/csgo/resource/csgo_english.txt"));

    using HttpResponseMessage response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);

    KVSerializer? serializer = KVSerializer.Create(KVSerializationFormat.KeyValues1Text);

    KVSerializerOptions options = new() {
        EnableValveNullByteBugBehavior = true,
        HasEscapeSequences = true
    };

    using Stream stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);

    serializer.Deserialize(stream, options);
}

Throws:

ValveKeyValue.KeyValueException: Found end of file when another token type was expected.
 ---> System.InvalidOperationException: Attempted to finalize object while in state InObjectBetweenKeyAndValue.

The same repro using HttpCompletionOption.ResponseContentRead instead of HttpCompletionOption.ResponseHeadersRead fixes the issue.

For some reason VKV can't work in this scenario, my blind guess is that it doesn't wait for the end of the stream but rather stops parsing in the middle while more data is being buffered, in result crashing as if the data was cut somewhere in the middle.

The proper logic in this case would include reading stream to the very end, also when being buffered and not fully ready yet.

Could also be something entirely different, I don't know. However, it's nice to note that other deserializing libraries (Newtonsoft.Json tested) work in this scenario just fine.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions