-
-
Save elanderson/c50b2107de8ee2ed856353dfed9168a2 to your computer and use it in GitHub Desktop.
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>(); | |
} | |
} |
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.
@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.
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.
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;
@petret It worked for me too, Thanks.
I had issue in POST
requests which request was sending null.
@shojajou check this link, you have to reset the position of the stream
I'm crying! Thank you all !!!
@ajithesh try the following:
- Swap lines 33 and 34 - so the
.EnableRewind()
is before the assignment;- Between line 38 and 39 insert
body.Seek(0, SeekOrigin.Begin)
.
Thanks!
@petret
thank uuuuuuuuuuuuu woooooooooooow!!!!!!!!
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
Great solution! But the statuscode 204 it's very danger for VS2017!!!
I add the following "if" before 27