'Is there a way to read a multipart response (produced by graphql @defer) one chunk at a time as it arrives in c#?

I am currently working with a GraphQL api that implements HotChocolate. The api is using the @defer directive to split the response up into a faster section of data and a slightly slower portion of data.

I am currently looking for a way to read each of those parts as they arrive in C# code. I have a solution that works in javascript that came from this youtube video, there is an approach using the fetch api at 16:00 and then one using the older XMLHttpRequest approach at 16:51.

The older approach ties into the events that happen on an XMLHttpRequest whilst the newer fetch approach readers the response as a stream.

// Taken from above linked video
const body = { query, variables }
const xhr = new XMLHttpRequest();
let index = 0;

xhr.open("POST", "https://localhost:7127/graphql/");
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.addEventListener("readystatechange", function onReadyStateChange() {
    const chunk = xhr.response.substring(index);
    handleChunk(chunk);
    index = xhr.response.length;
});

xhr.send(JSON.stringify(body));

Both approaches read (and display) the parts of the response as they arrive (usually about 0.5s apart). And the request states the response is a multipart/mixed response.

I have tried a few ways to read the response but all of them are like the below approach.

using (var httpClient = new HttpClient()) {
  using (var request = new HttpRequestMessage(new HttpMethod("POST"), "https://localhost:7127/graphql/")) {
    request.Content = JsonContent.Create(new {
        query = query,
        variables = variables
    });

    var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
    var stream = await response.Content.ReadAsStreamAsync();
    var reader = new StreamReader(stream);

    -- At this point the response is fully populated so has waited for the entire process
    Console.WriteLine(reader.ReadToEnd()); // Contains all the data
  }
}

Is there a way I can attach a listener to changes in the response for this request? Or a way to implement a stream so that parts can be read rather than waiting for the whole response?

Current solutions out there for @defer handling all involve npm packages or other js libraries. I need a way to do this in C# for use with NBomber testing. Originally I was using K6 for performance testing but the http client they have built doesn't allow for customisation and doesn't handle this use case.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source