I have a netcore 3 API application that logs the incoming request and then passes it on to the controller action.
My code looks like this:
public RequestLoggingHandler(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, RequestLoggingRequirement requirement)
{
try
{
var httpContext = _httpContextAccessor.HttpContext;
var request = httpContext.Request;
_repository = (ICleanupOrderRepository)httpContext.RequestServices.GetService(typeof(ICleanupOrderRepository));
_cache = (IMemoryCache)httpContext.RequestServices.GetService(typeof(IMemoryCache));
httpContext.Items["requestId"] = SaveRequest(request);
context.Succeed(requirement);
return Task.CompletedTask;
}
catch (Exception ex)
{
throw ex;
}
}
private int SaveRequest(HttpRequest request)
{
try
{
// Allows using several time the stream in ASP.Net Core
var buffer = new byte[Convert.ToInt32(request.ContentLength)];
request.Body.ReadAsync(buffer, 0, buffer.Length);
var requestContent = Encoding.UTF8.GetString(buffer);
var requestId = _repository.SaveRawHandlerRequest($"{request.Scheme} {request.Host}{request.Path} {request.QueryString} {requestContent}");
return requestId;
}
catch (Exception ex)
{
throw ex;
}
}
However when this request is passed on to the Controller the request body is null.
Previously in Core2.x you could do
request.EnableRewind();
My understanding is this is now replaced with
httpContext.Request.EnableBuffering();
However, even with
httpContext.Request.EnableBuffering();
the request body is still null once the request body is read.
How can I get around this ?
EnableBuffering(HttpRequest) Ensure the request Body can be read multiple times. Normally buffers request bodies in memory; writes requests larger than 30K bytes to disk. EnableBuffering(HttpRequest, Int32) Ensure the request Body can be read multiple times.
7+ Million HTTP requests per second from a single server.
It is a known issue on github.
A temp workaround is to pull out the body right after the call to EnableBuffering and then rewinding the stream to 0 and not disposing it:
public class RequestLoggingHandler : AuthorizationHandler<RequestLoggingRequirement>
{
private readonly IHttpContextAccessor _httpContextAccessor;
public RequestLoggingHandler(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, RequestLoggingRequirement requirement)
{
try
{
var httpContext = _httpContextAccessor.HttpContext;
var request = httpContext.Request;
request.EnableBuffering();
httpContext.Items["requestId"] = SaveRequest(request);
context.Succeed(requirement);
return Task.CompletedTask;
}
catch (Exception ex)
{
throw ex;
}
}
private int SaveRequest(HttpRequest request)
{
try
{
// Allows using several time the stream in ASP.Net Core
var buffer = new byte[Convert.ToInt32(request.ContentLength)];
request.Body.ReadAsync(buffer, 0, buffer.Length);
var requestContent = Encoding.UTF8.GetString(buffer);
var requestId = _repository.SaveRawHandlerRequest($"{request.Scheme} {request.Host}{request.Path} {request.QueryString} {requestContent}");
request.Body.Position = 0;//rewinding the stream to 0
return requestId;
}
catch (Exception ex)
{
throw ex;
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With