我的OWIN中间件是这样的。 (Framework是ASP.NET Web API)。
public class MyMiddleware : OwinMiddleware
{
public MyMiddleware(OwinMiddleware next) : base(next) { }
public override async Task Invoke(OwinRequest request, OwinResponse response)
{
var header = request.GetHeader("X-Whatever-Header");
await Next.Invoke(request, response);
response.SetHeader("X-MyResponse-Header", "Some Value");
response.StatusCode = 403;
}
}
问题:
推荐的做法是从OwinMiddleware
派生吗?我看到在Katana源代码中,一些中间件类派生自OwinMiddleware
,有些则不是。
我可以看到请求标头没问题。在我的中间件Next.Invoke
之后设置响应头或状态代码对返回给客户端的响应没有影响。但是,如果我在Next.Invoke
调用之前设置响应标头或状态,则带有标头的响应和我设置的状态将返回给客户端。设置这些的正确方法是什么?
答案 0 :(得分:27)
是的,推荐使用OwinMiddleware。一些中间件类不是从OwinMiddleware派生的原因是它们要么尚未切换,因为最近引入了类。或者为了避免程序集由于某种原因而依赖于Microsoft.Owin程序集。
在调用Next上的Invoke之后设置响应的可能原因是,一旦任何人开始写入响应正文流,响应HTTP标头就会被发送。因此,在中间件组件开始写入响应主体后对状态代码或HTTP标头的任何更改都不会产生任何影响。
你可以尝试做的是使用OWIN提供的OnSendingHeaders回调。以下是您可以使用它的方法:
public override async Task Invoke(IOwinContext context)
{
var response = context.Response;
var request = context.Request;
response.OnSendingHeaders(state =>
{
var resp = (OwinResponse)state;
resp.Headers.Add("X-MyResponse-Header", "Some Value");
resp.StatusCode = 403;
resp.ReasonPhrase = "Forbidden";
}, response);
var header = request.Headers["X-Whatever-Header"];
await Next.Invoke(context);
}
感谢cookiesit314更新我的回答。
答案 1 :(得分:8)
我试图编辑Youssef的优秀答案,以纠正一个小错误,并用OwinMiddleware现在的工作方式更新示例。
编辑被拒绝(好吧,一个人批准,一个人因为太小而被拒绝,两个因为太重要而被拒绝)。
以下是Youssef代码的版本:
public override async Task Invoke(IOwinContext context)
{
var response = context.Response;
var request = context.Request;
response.OnSendingHeaders(state =>
{
var resp = (OwinResponse)state;
resp.Headers.Add("X-MyResponse-Header", "Some Value");
resp.StatusCode = 403;
resp.ReasonPhrase = "Forbidden"; // if you're going to change the status code
// you probably should also change the reason phrase
}, response);
var header = request.Headers["X-Whatever-Header"];
await Next.Invoke(context);
}
答案 2 :(得分:0)
我使用这段代码来获取每个请求所花费的时间。
appBuilder.Use(async (context, next) =>
{
var watch = new Stopwatch();
watch.Start();
await next();
watch.Stop();
context.Response.Headers.Set("ResponseTime", watch.Elapsed.Seconds.ToString());
});