Question

This question is related to the excellent answer by Youssef. I love OnSendingHeaders callback. I can now add the response headers without worrying about switching streams. Anyways, here is my question. Is it possible to read the response body inside the callback, like so.

public override async Task Invoke(OwinRequest request, OwinResponse response)
{
    request.OnSendingHeaders(state =>
        {
            var resp = (OwinResponse)state;
            // Here, I want to convert resp, which is OwinResponse
            // to HttpResponseMessage so that when Content.ReadAsStringAsync
            // is called off this HttpResponseMessage object, I want the 
            // response body as string.

            var responseMessage = new HttpResponseMessage();
            responseMessage.Content = new StreamContent(resp.Body);
            // Here I would like to call
            // responseMessage.Content.ReadAsStringAsync()

        }, response);


    await Next.Invoke(request, response);

}

The methods I want to call from the callback are part of classes that depend on HttpResponseMessage and do not want to change them.

If I set the response body to memory stream before the pipeline processing starts (as was initially suggested by Youssef in the linked answer), I'm able to get this working. Is there a better way to do this here in the callback instead of that?

EDIT:

Is this okay?

public override async Task Invoke(OwinRequest request, OwinResponse response)
{
    // Do something with request

    Stream originalStream = response.Body;

    var buffer = new MemoryStream();
    response.Body = buffer;

    await Next.Invoke(request, response);

    var responseMessage = new HttpResponseMessage();

    response.Body.Seek(0, SeekOrigin.Begin);

    responseMessage.Content = new StreamContent(response.Body);

    // Pass responseMessage to other classes for the
    // response body to be read like  this
    // responseMessage.Content.ReadAsStringAsyn()
    // Add more response headers

    if (buffer != null && buffer.Length > 0)
    {
        buffer.Seek(0, SeekOrigin.Begin);
        await buffer.CopyToAsync(originalStream);
    }
}
Was it helpful?

Solution

What do you want to do with the response body?

This callback is invoked on first write, so it's too late to replace the stream. You also can't read from the response stream as there is nothing stored in it normally. This is normally a write-only stream that goes out to the network.

Replacing the response stream earlier is the correct approach here.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top