32

我的 OWIN 中间件是这样的。(框架是 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;

    }
}

问题:

  1. 这是推荐的做法OwinMiddleware吗?我看到在 Katana 源代码中,一些中间件类派生自OwinMiddleware,而有些则没有。

  2. 我可以看到请求标头没问题。在我的中间件中设置响应头或状态码Next.Invoke对返回给客户端的响应没有影响。但是,如果我在Next.Invoke调用之前设置了响应标头或状态,则带有标头的响应和我设置的状态将返回给客户端。设置这些的正确方法是什么?

4

3 回答 3

34
  1. 是的,推荐从 OwinMiddleware 派生。一些中间件类不派生自 OwinMiddleware 的原因是它们尚未切换,因为该类是最近引入的。或者为了避免使程序集因某种原因依赖于 Microsoft.Owin 程序集。

  2. 调用 Invoke on Next 后在响应上设置内容不起作用的可能原因是,只要有人开始写入响应正文流,就会发送响应 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);
}

感谢 biscuit314 更新我的答案。

于 2013-07-07T14:59:25.727 回答
11

我尝试编辑 Youssef 的出色答案以纠正一个小错误,并使用 OwinMiddleware 现在的工作方式更新示例。

编辑被拒绝(好吧,一个人批准,一个人因为太小被拒绝,另一个人因为太重要而被拒绝)。

这是优素福代码的那个版本:

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);
}
于 2014-03-02T18:25:37.990 回答
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());
        });
于 2020-01-31T10:12:49.627 回答