我想像这样在我的ASP.NET Core WebApi中添加一个处理时中间件
public class ProcessingTimeMiddleware
{
private readonly RequestDelegate _next;
public ProcessingTimeMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
var watch = new Stopwatch();
watch.Start();
await _next(context);
context.Response.Headers.Add("X-Processing-Time-Milliseconds", new[] { watch.ElapsedMilliseconds.ToString() });
}
}
Run Code Online (Sandbox Code Playgroud)
但这样做会引发异常
System.InvalidOperationException: Headers are readonly, reponse has already started.
Run Code Online (Sandbox Code Playgroud)
如何在响应中添加标头?
Gil*_*rdo 46
没关系,代码在这里
public async Task Invoke(HttpContext context)
{
var watch = new Stopwatch();
watch.Start();
//To add Headers AFTER everything you need to do this
context.Response.OnStarting(state => {
var httpContext = (HttpContext)state;
httpContext.Response.Headers.Add("X-Response-Time-Milliseconds", new[] { watch.ElapsedMilliseconds.ToString() });
return Task.CompletedTask;
}, context);
await _next(context);
}
Run Code Online (Sandbox Code Playgroud)
或者,您也可以直接在Startup.cs Configure方法中添加中间件.
app.Use(
next =>
{
return async context =>
{
var stopWatch = new Stopwatch();
stopWatch.Start();
context.Response.OnStarting(
() =>
{
stopWatch.Stop();
context.Response.Headers.Add("X-ResponseTime-Ms", stopWatch.ElapsedMilliseconds.ToString());
return Task.CompletedTask;
});
await next(context);
};
});
app.UseMvc();
Run Code Online (Sandbox Code Playgroud)
在将任何内容写入响应主体之后,无法设置响应头。一旦将请求传递给下一个中间件并将其写入响应,那么中间件就无法再次设置响应头。
但是,有一种使用回调方法的解决方案。
Microsoft.AspNetCore.Http.HttpResponse定义OnStarting方法,该方法将在响应标头发送到客户端之前添加要调用的委托。您可以将此方法视为回调方法,该方法将在写入响应开始之前立即被调用。
public class ResponseTimeMiddleware
{
private const string RESPONSE_HEADER_RESPONSE_TIME = "X-Response-Time-ms";
private readonly RequestDelegate _next;
public ResponseTimeMiddleware(RequestDelegate next)
{
_next = next;
}
public Task InvokeAsync(HttpContext context)
{
var watch = new Stopwatch();
watch.Start();
context.Response.OnStarting(() =>
{
watch.Stop();
var responseTimeForCompleteRequest = watch.ElapsedMilliseconds;
context.Response.Headers[RESPONSE_HEADER_RESPONSE_TIME] = responseTimeForCompleteRequest.ToString();
return Task.CompletedTask;
});
// Call the next delegate/middleware in the pipeline
return this._next(context);
}
}
Run Code Online (Sandbox Code Playgroud)
在相关说明中,在不回答您的问题的情况下,现在有一个Server-Timing规范,一个标准标头来提供持续时间以及其他指标。这应该允许您使用
Server-Timing: processingTime;dur=12ms
Run Code Online (Sandbox Code Playgroud)
您可以在https://www.w3.org/TR/server-timing/找到该规范
| 归档时间: |
|
| 查看次数: |
30826 次 |
| 最近记录: |