0

I'm building a piece of middleware that automatically logs the information of inbound requests and their responses from an API. As part of that I would like to be able to log the body of the request, however this is a bit more difficult since I'm working with streams.

Currently, the middleware will read the body and log it, however since I'm reading the body using a StreamReader the contents of the body becomes essentially null after, since it's been read. Because of this the request continues and I'm getting "A non-empty request body is required." errors since there's no body present any longer in the request.

I want to be able to copy the stream over to a new variable so that I can read the second variable and log the body while keeping the original body of the request intact so it can proceed and be processed by my controller.

I've tried the below, but since this just creates a reference to the stream, the original is still affected.

public void AddInboundDetails(HttpRequest request)
        {
            var bodyStreamCopy = request.Body;
            Add("requestBody", ReadStreamAsString(bodyStreamCopy));
        }

private string ReadStreamAsString(Stream input)
        {
            StreamReader reader = new StreamReader(input, Encoding.UTF8);
            return reader.ReadToEnd();
        }

I've read about Stream.CopyTo in the docs, but since this is again reading the original stream it feels like this will just produce the same problem.

Update, same issue:

request.EnableBuffering();
var body = request.Body;
var buffer = new byte[Convert.ToInt32(request.ContentLength)];
await request.Body.ReadAsync(buffer, 0, buffer.Length);
var bodyAsText = Encoding.UTF8.GetString(buffer);
request.Body = body;
Jake12342134
  • 1,539
  • 1
  • 18
  • 45
  • See e.g. [here](https://stackoverflow.com/questions/40494913/how-to-read-request-body-in-an-asp-net-core-webapi-controller) or [here](https://exceptionnotfound.net/using-middleware-to-log-requests-and-responses-in-asp-net-core/) or [here](https://referbruv.com/blog/posts/logging-http-request-and-response-in-aspnet-core-using-middlewares). The thing you need is `request.EnableBuffering()`, which adds buffering to the request, so that it can be read multiple times (it will still need rewinding of course) – canton7 Dec 11 '20 at 13:33
  • @canton7 I've added an update to the post using info from the blog post, however I'm still getting the same issue. – Jake12342134 Dec 11 '20 at 13:56
  • Yeah, it looks like the blog post is missing the crucial step of actually rewinding the request stream (and it's the rewinding operation which is enabeld by `EnableBuffering()`). Some of the answers in my first link look to be doing this – canton7 Dec 11 '20 at 13:59
  • @canton7 Am I to EnableBuffering() or EnableRewind()? There seems to be some differing use – Jake12342134 Dec 11 '20 at 14:02
  • `EnableRewind` [is now internal](https://source.dot.net/#Microsoft.AspNetCore.Http/Internal/BufferingHelper.cs,47b7015acb14f2a4). `EnableBuffering` [calls `EnableRewind`](https://source.dot.net/#Microsoft.AspNetCore.Http/Extensions/HttpRequestRewindExtensions.cs,8c292fc78d27f547). They just renamed the method. – canton7 Dec 11 '20 at 14:03

0 Answers0