0

I have a middleware to track performance of my custom developed gateway in ASP.NET Core 2.2 API. I have used the this post from StackOverflow.

Basically the main part is as follows :

public class ResponseRewindMiddleware {
    private readonly RequestDelegate next;

    public ResponseRewindMiddleware(RequestDelegate next) {
        this.next = next;
    }

    public async Task Invoke(HttpContext context) {

        Stream originalBody = context.Response.Body;
        /* MY CODE COMES HERE */

        try {
            using (var memStream = new MemoryStream()) {
                context.Response.Body = memStream;

                await next(context);

                memStream.Position = 0;
                string responseBody = new StreamReader(memStream).ReadToEnd();

                memStream.Position = 0;
                await memStream.CopyToAsync(originalBody);
            }

        } finally {
            context.Response.Body = originalBody;
        }

    } 

This code runs OK. But I want to log the input (a JSON body) to the gateway and I add the following lines :

using (System.IO.StreamReader rd = new System.IO.StreamReader(context.Request.Body))
{
    bodyStr = rd.ReadToEnd();
}

This reads the input body from Request but the flow is broken and the rest of the process does not flow resulting in a "HTTP 500 Internal Server Error". I assume reading the Request body via a Stream breaks something.

How can I read the Request body without breaking the flow?

user3021830
  • 2,784
  • 2
  • 22
  • 43
  • Why wrap the reader with a `using(){....}`? It will dispose the Request.Body when out of scope. Besides, you forget to rewind the Body stream to position 0? – itminus Jan 17 '20 at 08:33
  • Maybe you can refer to [How to read request body in a asp.net core webapi controller?](https://stackoverflow.com/questions/40494913/how-to-read-request-body-in-a-asp-net-core-webapi-controller), in particular you should be using [EnableBuffering](https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.http.httprequestrewindextensions.enablebuffering?view=aspnetcore-3.1) if you are reading the request stream multiple times – scharnyw Jan 17 '20 at 08:51

1 Answers1

1

The idea is to call EnableBuffering to enable multiple read, and then to not dispose the request body after you have done reading it. The following works for me.

// Enable the request body to be read in the future
context.Request.EnableBuffering();

// Read the request body, but do not dispose it
var stream = new StreamReader(context.Request.Body);            
string requestBody = await stream.ReadToEndAsync();

// Reset to the origin so the next read would start from the beginning
context.Request.Body.Seek(0, SeekOrigin.Begin);
YYTan
  • 471
  • 1
  • 5
  • 21