Skip to content

Instantly share code, notes, and snippets.

@elanderson
Created February 7, 2017 12:46
Show Gist options
  • Select an option

  • Save elanderson/c50b2107de8ee2ed856353dfed9168a2 to your computer and use it in GitHub Desktop.

Select an option

Save elanderson/c50b2107de8ee2ed856353dfed9168a2 to your computer and use it in GitHub Desktop.
Request Response Logging Middleware for ASP.NET Core
public class RequestResponseLoggingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger _logger;
public RequestResponseLoggingMiddleware(RequestDelegate next,
ILoggerFactory loggerFactory)
{
_next = next;
_logger = loggerFactory
.CreateLogger<RequestResponseLoggingMiddleware>();
}
public async Task Invoke(HttpContext context)
{
_logger.LogInformation(await FormatRequest(context.Request));
var originalBodyStream = context.Response.Body;
using (var responseBody = new MemoryStream())
{
context.Response.Body = responseBody;
await _next(context);
_logger.LogInformation(await FormatResponse(context.Response));
await responseBody.CopyToAsync(originalBodyStream);
}
}
private async Task<string> FormatRequest(HttpRequest request)
{
var body = request.Body;
request.EnableRewind();
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;
return $"{request.Scheme} {request.Host}{request.Path} {request.QueryString} {bodyAsText}";
}
private async Task<string> FormatResponse(HttpResponse response)
{
response.Body.Seek(0, SeekOrigin.Begin);
var text = await new StreamReader(response.Body).ReadToEndAsync();
response.Body.Seek(0, SeekOrigin.Begin);
return $"Response {text}";
}
}
public static class RequestResponseLoggingMiddlewareExtensions
{
public static IApplicationBuilder UseRequestResponseLogging(this IApplicationBuilder builder)
{
return builder.UseMiddleware<RequestResponseLoggingMiddleware>();
}
}
@ajithesh

ajithesh commented Dec 6, 2017

Copy link
Copy Markdown

I am able to get the response when i do a GET. But when i do a POST, i expect my data to come to Request object. But that is missing. Can someone put your solutions?

@petret

petret commented Jan 12, 2018

Copy link
Copy Markdown

@ajithesh try the following:

  1. Swap lines 33 and 34 - so the .EnableRewind()is before the assignment;
  2. Between line 38 and 39 insert body.Seek(0, SeekOrigin.Begin).

@israelquiroz93

Copy link
Copy Markdown

@petret worked like a charm

@LorenzoSerino

Copy link
Copy Markdown

Great solution! But the statuscode 204 it's very danger for VS2017!!!

I add the following "if" before 27

//Because you change the response body which is not allowed on a 204.
if (context.Response.StatusCode!=204) 
     await responseBody.CopyToAsync(originalBodyStream);

@mikeloguay

Copy link
Copy Markdown

Thanks @petret, the same behaviour (request body null on POSTs) on my side, and thid change solved it.

@elanderson it would be nice if you update the code with the fix.

Many thanks.

@georgekargakis

georgekargakis commented Sep 14, 2018

Copy link
Copy Markdown

@elanderson thank you for sharing the approach of using a middleware in order to log request/responses in an asp.netcore application. However the specific solution might cause memory leak in case of large body in request and response. Please check an alternative approach that might eradicate the risk of memory leak. Feel free to send your feedback so we can end up in a more elegant solution.

@frocksgamer

frocksgamer commented Sep 27, 2018

Copy link
Copy Markdown

Hello all.
With every solutions posted here, I my Webapi core 2.1 still not working with POSTS requests, send for example by PostMan.
The POST requests simple does not trigger Invoke method. The GET request works like a charm.
Even doing mr. @petret alterations.
Any option?
Thanks.

@CoviloMilos

Copy link
Copy Markdown

Remove this part from code and it will forward body of post.
var body = request.Body;
request.EnableRewind();

    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;

@c0d3sling3r

c0d3sling3r commented Apr 6, 2019

Copy link
Copy Markdown

@petret It worked for me too, Thanks.
I had issue in POST requests which request was sending null.

@alesshosry

Copy link
Copy Markdown

@shojajou check this link, you have to reset the position of the stream

@Bazooka2091

Bazooka2091 commented Nov 27, 2019

Copy link
Copy Markdown

I'm crying! Thank you all !!!

@ajithesh try the following:

  1. Swap lines 33 and 34 - so the .EnableRewind()is before the assignment;
  2. Between line 38 and 39 insert body.Seek(0, SeekOrigin.Begin).

Thanks!

@ghasemi1994

Copy link
Copy Markdown

@petret
thank uuuuuuuuuuuuu woooooooooooow!!!!!!!!

@unseensenpai

unseensenpai commented Sep 21, 2023

Copy link
Copy Markdown

I struggelered a lot with body request null.

Tried on .NET 8 and working fine. Added some cool details and json limit (100 char) for log file size.

Request Response Logging in .Net 8
You can find all files here for implementation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment