【发布时间】:2021-05-03 19:35:34
【问题描述】:
我目前正在 .NET 5 中开发 API,需要向 API 添加请求和响应日志记录。我能够轻松记录请求正文和标头。我也能够毫无问题地记录响应正文。出现的问题是当我想记录响应标头时。我目前只能访问Content-Length 和Content-Type。
在 Postman 中查找我收到的请求的响应时:
DateContent-TypeServerContent-LengthX-Rate-Limit-LimitX-Rate-Limit-RemainingX-Rate-Limit-Reset
X-Rate-Limit- 是应用程序中的中间件。我试图在Startup.cs 中的这个中间件的上方和下方添加我的中间件,其中没有一个返回这些标头。我有一种感觉,这就是创建请求时我在中间件中管理响应对象的方式。
这是我的中间件的样子:
namespace X.API.Middleware
{
public class RequestResponseLoggingMiddleware
{
/// <summary>
/// Request delegate that allows us to move the middleware along
/// </summary>
private readonly RequestDelegate _next;
/// <summary>
/// Constructor for DI
/// </summary>
/// <param name="next"></param>
public RequestResponseLoggingMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
//Enable buffering so that the streams can be read
context.Request.EnableBuffering();
//Read the request body to a string for logging
var requestBodyString = await new StreamReader(context.Request.Body).ReadToEndAsync();
//Read the request headers
var requestHeaders = context.Request.Headers.ToDictionary(a => a.Key, a => a.Value);
//Log the incoming request
LogContext.PushProperty("RequestBody", requestBodyString);
LogContext.PushProperty("RequestHeaders", requestHeaders);
Log.Information("Incoming Request");
//Reset the position of the request body so it doesn't seem read
context.Request.Body.Position = 0;
//Create a new body to be used
var originalBody = context.Response.Body;
await using var newBody = new MemoryStream();
context.Response.Body = newBody;
//Calls the next middleware
await _next(context);
//Seeks the body back
newBody.Seek(0, SeekOrigin.Begin);
//Read the response body string
var responseBodyString = await new StreamReader(context.Response.Body).ReadToEndAsync();
//Read the response headers
var responseHeaders = context.Response.Headers.ToDictionary(a => a.Key, a => a.Value);
//Check if the URL is not a documentation URL
if (!context.Request.Path.ToString().Contains("api-docs") && !context.Request.Path.ToString().Contains("swagger"))
{
//Reset custom props
LogContext.Reset();
//Log the response
LogContext.PushProperty("ResponseBody", responseBodyString);
LogContext.PushProperty("ResponseHeaders", responseHeaders);
Log.Information("Outgoing Response");
}
//Return the original body
newBody.Seek(0, SeekOrigin.Begin);
await newBody.CopyToAsync(originalBody);
}
}
}
而Startup.cs中的中间件注册如下:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ApiContext context) {
app.UseRequestResponseLogging();
//Enable rate limiting
app.UseIpRateLimiting();
app.UseExceptionHandler(errorApp => errorApp.Run(ExceptionHandler.HandleException()));
app.UseSwagger();
app.UseReDoc(c => {
c.DocumentTitle = "Curo API Documentation";
c.SpecUrl = "/swagger/v1/swagger.json";
});
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints => {
endpoints.MapControllers();
});
Log.Information("Application started!");
}
有问题的中间件是UseRequestResponseLogging。我尝试将中间件放在顶部和底部,它们之间没有区别,因为我相信到那时请求和响应已经设置好了。
【问题讨论】:
标签: c# asp.net-core asp.net-core-webapi