如何多次读取 net core 3 中的 http 请求正文?
How can I read http request body in netcore 3 more than once?
我有一个 netcore 3 API 应用程序,它记录传入的请求,然后将其传递给控制器操作。
我的代码如下所示:
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;
}
}
但是,当此请求传递给控制器时,请求正文为空。
以前在 Core2.x 你可以做
request.EnableRewind();
我的理解是这现在被替换为
httpContext.Request.EnableBuffering();
然而,即使
httpContext.Request.EnableBuffering();
读取请求体后,请求体仍然为空。
我该如何解决这个问题?
这是 github 上的已知 issue。
临时解决方法是在调用 EnableBuffering 后立即拉出主体,然后将流倒回 0 并且不处理它:
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;
}
}
}
我有一个 netcore 3 API 应用程序,它记录传入的请求,然后将其传递给控制器操作。
我的代码如下所示:
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;
}
}
但是,当此请求传递给控制器时,请求正文为空。
以前在 Core2.x 你可以做
request.EnableRewind();
我的理解是这现在被替换为
httpContext.Request.EnableBuffering();
然而,即使
httpContext.Request.EnableBuffering();
读取请求体后,请求体仍然为空。
我该如何解决这个问题?
这是 github 上的已知 issue。
临时解决方法是在调用 EnableBuffering 后立即拉出主体,然后将流倒回 0 并且不处理它:
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;
}
}
}