Owin 中间件 return 的响应能否早于 Invoke 方法 return?

Can an Owin Middleware return a response earlier than the Invoke method returns?

我有以下中间件代码:

public class UoWMiddleware : OwinMiddleware
{
    readonly IUoW uow;
    public UoWMiddleware(OwinMiddleware next, IUoW uow) : base(next)
    {
        this.uow = uow;
    }

    public override async Task Invoke(IOwinContext context)
    {
        try
        {
            await Next.Invoke(context);
        }
        catch
        {
            uow.RollBack();
            throw;
        }
        finally
        {
            if (uow.Status == Base.SharedDomain.UoWStatus.Running)
            {
                var response = context.Response;
                if (response.StatusCode < 400)
                {
                    Thread.Sleep(1000);
                    uow.Commit();
                }
                else
                    uow.RollBack();
            }
        }
    }
}

偶尔我们观察到在通过 fiddler 调用 uow.Commit() 之前对客户端的响应 returns。例如,我们在 uow.Commit 上设置了一个断点,尽管我们正在断点等待,但我们看到响应已 returned 到客户端。这有些出乎意料。我认为在 Invoke 方法结束后响应将严格 return 。我错过了什么吗?

在 Owin/Katana 中,当中间件调用 Write 时,响应 body(当然还有 headers)被发送到客户端Response object 的 IOwinContext.

这意味着如果您的 next 中间件正在写入响应 body 您的客户端将在您的 server-side 代码 returns 之前收到它调用 await Next.Invoke().

这就是 Owin 的设计方式,并且取决于响应流可能在单个 Request/Response life-cycle.

中仅写入一次这一事实

查看您的代码,我看不出这种行为有任何重大问题,因为您只是在将响应写入流后读取响应 headers,因此不会更改它。

相反,如果您需要更改下一个中间件编写的响应,或者您严格需要在 执行进一步逻辑 server-side 之后编写响应 ,那么你唯一的选择是将响应 body 缓冲到内存流中,然后在准备好时将其复制到真正的响应流 (as per this answer) 中。

我已经在不同的用例(但共享相同的概念)中成功测试了这种方法,您可能会在查看此答案时发现:https://whosebug.com/a/36755639/3670737

参考:
Changing the response object from OWIN Middleware